数据结构算法-哈希表:四数之和
1.1 、问题描述:四数之和
力扣题目链接
https://leetcode.cn/problems/4sum/
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < na、b、c和d互不相同nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

1.2、核心思路拆解(清晰版):
-
排序先行:数组排序后,既能通过双指针灵活调整总和,又能让重复元素相邻,方便去重。
-
两层循环固定前两数:
- 第一层循环固定第一个数
a = nums[k],第二层循环固定第二个数b = nums[i](i > k避免重复)。
- 第一层循环固定第一个数
-
剪枝优化:
- 当
a或a+b已大于target,且当前和为正或target为正(避免负数场景误剪),后续数更大,总和必超target,直接 break。
- 当
-
去重逻辑:
- 对
a:若nums[k] == nums[k-1](k>0),跳过(避免重复四元组)。 - 对
b:若nums[i] == nums[i-1](i>k+1),跳过(确保不与前一个b重复)。
- 对
-
双指针找后两数:
left从i+1开始(c),right从数组末尾开始(d)。- 计算四数总和:
- 总和 > target →
right--(减小d); - 总和 < target →
left++(增大c); - 总和 = target → 加入结果,同时跳过重复的
c和d,再移动指针继续找。
- 总和 > target →
1.3、代码实现
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class FourSum {// 四数之和:返回所有不重复的四元组 (a,b,c,d) 使得 a+b+c+d = targetpublic List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> result = new ArrayList<>();int n = nums.length;// 边界条件:数组元素不足4个,直接返回空if (n < 4) {return result;}// 1. 排序数组(核心前提:为双指针移动和去重提供基础)Arrays.sort(nums);// 2. 第一层循环:固定第一个数 a = nums[k]for (int k = 0; k < n - 3; k++) {// 剪枝优化:若当前a已大于target,且a为正或target为正,后续数更大,总和必超targetif (nums[k] > target && (nums[k] >= 0 || target >= 0)) {break;}// 去重a:当前a与前一个a相同,跳过(避免重复四元组)if (k > 0 && nums[k] == nums[k - 1]) {continue;}// 3. 第二层循环:固定第二个数 b = nums[i](i从k+1开始,确保a在b左侧)for (int i = k + 1; i < n - 2; i++) {// 剪枝优化:a+b已大于target,且a+b为正或target为正,后续数更大,总和必超targetlong sumAB = (long) nums[k] + nums[i]; // 用long避免int溢出if (sumAB > target && (sumAB >= 0 || target >= 0)) {break;}// 去重b:当前b与前一个b相同(且前一个b的位置在k之后),跳过if (i > k + 1 && nums[i] == nums[i - 1]) {continue;}// 4. 双指针找 c 和 d:c在b右侧,d在数组末尾int left = i + 1; // c = nums[left]int right = n - 1; // d = nums[right]// 5. 根据四数之和调整指针while (left < right) {long total = sumAB + nums[left] + nums[right]; // 用long避免溢出if (total > target) {// 总和太大,右指针左移(减小d)right--;} else if (total < target) {// 总和太小,左指针右移(增大c)left++;} else {// 找到有效四元组,加入结果result.add(Arrays.asList(nums[k], nums[i], nums[left], nums[right]));// 去重c:跳过重复的c值(避免同一a、b下的重复四元组)while (left < right && nums[left] == nums[left + 1]) {left++;}// 去重d:跳过重复的d值while (left < right && nums[right] == nums[right - 1]) {right--;}// 移动指针,继续寻找下一组c、dleft++;right--;}}}}return result;}// 测试public static void main(String[] args) {FourSum solution = new FourSum();int[] nums = {1, 0, -1, 0, -2, 2};int target = 0;List<List<Integer>> result = solution.fourSum(nums, target);System.out.println("符合条件的四元组有 " + result.size() + " 个:");for (List<Integer> quad : result) {System.out.println(quad);}}
}
个人总结学习用,对部分内容进行了简单的处理和归纳,如有谬误,希望大家指出,
持续修订更新中。
参考文档:
- 程序员 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.
