1.1 、问题描述:四数相加II
力扣题目链接
https://leetcode.cn/problems/4sum-ii/
给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。
为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -2^28 到 2^28 - 1 之间,最终结果不会超过 2^31 - 1 。
例如:
输入:
A = [ 1, 2]
B = [-2,-1]
C = [-1, 2]
D = [ 0, 2]
输出:
2
解释:
两个元组如下:
(0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
(1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
1.2、思路:
核心思想:分组+哈希表
用哈希表(如 Java 中的 HashMap)存储第一组的两数和,key 为 某一次sum的具体值,value 为该和出现的次数。
分组处理:将四个数组分为两组(A和B为一组,C和D为另一组)。
- 预处理第一组:遍历 A 和 B 的所有元素组合,计算每对元素的和(a + b),并以该和为键,出现次数为值,存入哈希表中。例如,使用
map.getOrDefault(sum, 0)来统计次数(Java) - 处理第二组:遍历 C 和 D 的所有元素组合,计算每对元素的和(c + d),并检查哈希表中是否存在键
-(c + d)(即 0 - (c + d))。若存在,则将对应的值(即出现次数)累加到结果中。 - 返回结果:累计的次数即为满足条件的元组数量。
这就是哈希表的 “空间换时间” 特性
1.3 、指针数组示意图:

可以看到 A+B的sum值会作为key ,而的 A+B可能会有多个相同的值,即使用value存储。如:
A+B的-1 出现两次对应 就是 -1 作为key 2作为value
第一轮结果 :C+D和 A+B的值校验的结果,如果存在符合条件的。即key=tar=-(C+D)。value就是出现的次数 。

1.4、代码实现
import java.util.HashMap;
import java.util.Map;
/**
* 解决LeetCode 454.四数相加II问题
* 题目:给定4个整数数组nums1、nums2、nums3、nums4,计算有多少个元组(a,b,c,d)
* 使得a∈nums1, b∈nums2, c∈nums3, d∈nums4 且 a+b+c+d=0
*/
public class FourSumCount {
/**
* 核心方法:计算满足条件的四元组数量
* @param nums1 第一个整数数组
* @param nums2 第二个整数数组
* @param nums3 第三个整数数组
* @param nums4 第四个整数数组
* @return 满足a+b+c+d=0的四元组总数
*/
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
// 1. 创建哈希表存储"两数和"与"出现次数"的映射
// 为什么用哈希表?因为要快速查询"某个和是否存在"以及"存在多少次",时间复杂度O(1)
// key: nums1和nums2中任意两数的和(a+b)
// value: 这个和出现的次数(即有多少对(a,b)能算出这个和)
Map<Integer, Integer> sumMap = new HashMap<>();
// 2. 遍历nums1和nums2,计算所有可能的a+b,并统计次数存入哈希表
// 为什么遍历这两个数组?因为要把四数相加拆成两组(a+b)和(c+d),降低复杂度
// 外层循环:取出nums1中的每个元素a
for (int a : nums1) {
// 内层循环:取出nums2中的每个元素b
for (int b : nums2) {
// 计算当前a和b的和
int sumAB = a + b;
// 把sumAB存入哈希表,并更新出现次数
// getOrDefault(sumAB, 0):如果sumAB已存在,取它的次数;否则取默认值0
// +1:表示当前(a,b)组合又贡献了一次这个和
sumMap.put(sumAB, sumMap.getOrDefault(sumAB, 0) + 1);
}
}
// 3. 初始化结果变量,用于累计满足条件的四元组数量
int result = 0;
// 4. 遍历nums3和nums4,计算所有可能的c+d,寻找能凑成0的组合
// 为什么遍历这两个数组?因为目标是a+b + c+d = 0 → 即a+b = -(c+d)
// 外层循环:取出nums3中的每个元素c
for (int c : nums3) {
// 内层循环:取出nums4中的每个元素d
for (int d : nums4) {
// 计算当前c和d的和
int sumCD = c + d;
// 计算需要的目标和:能与sumCD凑成0的a+b应该是 -sumCD
int targetSumAB = -sumCD;
// 从哈希表中查询targetSumAB的出现次数
// 如果存在,说明有这么多对(a,b)能与当前(c,d)组成满足条件的四元组
// 把这个次数加到结果中
result += sumMap.getOrDefault(targetSumAB, 0);
}
}
// 5. 返回最终统计的四元组总数
return result;
}
// 测试代码:用具体例子验证逻辑
public static void main(String[] args) {
FourSumCount solution = new FourSumCount();
// 测试用例:4个简单数组
int[] nums1 = {1, 2};
int[] nums2 = {-1, 3};
int[] nums3 = {-2, 4};
int[] nums4 = {0, -3};
// 调用方法计算结果
int count = solution.fourSumCount(nums1, nums2, nums3, nums4);
// 预期结果:1(对应四元组(2,3,-2,-3),因为2+3+(-2)+(-3)=0)
System.out.println("满足条件的四元组数量:" + count); // 输出:1
}
}
个人总结学习用,对部分内容进行了简单的处理和归纳,如有谬误,希望大家指出,
持续修订更新中。
参考文档:
- 程序员 Carl. 代码随想录(LeetCode 数据结构与算法刷题攻略)(EB/OL). https://www.programmercarl.com/,2025-02/2025-10.
- 《数据结构》课程教学大纲(2024 版)(EB/OL). https://m.book118.com/html/2024/0423/8110022111006061.shtm,2024-04/2025-10.
- 《数据结构》课程教学大纲(软件工程专业)(EB/OL). https://m.renrendoc.com/paper/329728026.html,2024-05/2025-10.
- 程序员 Carl. LeetCode-Master(代码随想录刷题攻略 GitHub 仓库)(EB/OL). https://github.com/youngyangyang04/leetcode-master,2025-09/2025-10.
3025



被折叠的 条评论
为什么被折叠?



