题目(四数相加 II)
本质是:给你 4 个数组 A、B、C、D统计有多少个四元组(i, j, k, l)满足A[i] + B[j] + C[k] + D[l] == 0
关键点
数组长度一般 ≤ 200
暴力 4 重循环是O(n^4)→必超时
核心思想:把「四数相加」拆成「两数相加 + 两数相加」
这是这道题的灵魂。
数学变形
A[i] + B[j] + C[k] + D[l] = 0 ↓ (A[i] + B[j]) = -(C[k] + D[l])
也就是说:
只要某个 (a + b)等于某个 -(c + d)那么它们就能凑成 0
为什么用 unordered_map?
因为你需要做两件事:
统计 A + B 的所有可能结果
快速查找 -(C + D) 是否存在
哈希表刚好满足:
插入:O(1)
查找:O(1)
代码:
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) { unordered_map<int, int> umap; //key:a+b的数值,value:a+b数值出现的次数 // 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中 for (int a : A) { for (int b : B) { umap[a + b]++; } } int count = 0; // 统计a+b+c+d = 0 出现的次数 // 再遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。 for (int c : C) { for (int d : D) { if (umap.find(0 - (c + d)) != umap.end()) { count += umap[0 - (c + d)]; } } } return count; }时间复杂度分析
| 部分 | 复杂度 |
|---|---|
| 构建 A+B | O(n²) |
| 遍历 C+D | O(n²) |
| 哈希查找 | O(1) |