本文最后更新于:2026年5月6日 晚上
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = ,和 target = 0。 满足要求的四元组集合为:
Solution
参考:[15 三数之和](15 三数之和.md) 、**@Sean-87**
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Solution : def fourSum (self, nums: List[int ], target: int ) -> List[List[int]]: nums = sorted (nums) length = len (nums) if not nums or length<4 : return [] res = [] def twoSum (nums, start, target ): low, high = start, len (nums)-1 res = [] while low<high: sumLR = nums[low]+nums[high] left, right = nums[low], nums[high] if sumLR<target: while low<high and nums[low]==left: low+=1 elif sumLR>target: while low<high and nums[high]==right: high-=1 else : res.append([left, right]) while low<high and nums[low]==left: low+=1 while low<high and nums[high]==right: high-=1 return res for a in range (len (nums)-3 ): if a>0 and nums[a]==nums[a-1 ]: continue for b in range (a+1 , len (nums)-2 ): if b>a+1 and nums[b]==nums[b-1 ]: continue subRes = twoSum(nums, b+1 , target-nums[a]-nums[b]) for sub in subRes: sub.append(nums[a]) sub.append(nums[b]) res.append(sub) return res
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 class Solution {public : vector <vector <int >> fourSum(vector <int >& nums, int target) { vector <vector <int >> res; if (nums.size()<4 ) return res; sort(nums.begin(), nums.end()); for (int i=0 ; i<nums.size()-3 ; i=nextIndex(nums, i)){ for (int j=i+1 ; j<nums.size()-2 ; j=nextIndex(nums, j)){ int t = target-nums[i]-nums[j]; vector <vector <int >> subRes = twoSum(nums, j+1 , t); for (auto sub : subRes){ sub.push_back(nums[j]); sub.push_back(nums[i]); res.push_back(sub); } } } return res; }private : vector <vector <int >> twoSum(vector <int >& nums, int start, int target) { vector <vector <int >> result; int left=start, right=nums.size()-1 ; while (left<right){ int sum = nums[left]+nums[right]; int low = nums[left], high = nums[right]; if (sum <target){ while (left<right && nums[left]==low) left+=1 ; } else if (sum>target){ while (left<right && nums[right]==high) right-=1 ; } else { result.push_back({nums[left], nums[right]}); while (left<right && nums[left]==low) left+=1 ; while (left<right && nums[right]==high) right-=1 ; } } return result; } int nextIndex (const vector <int >& nums, int index) { for (int i=index+1 ; i<nums.size(); ++i){ if (nums[i] != nums[index]) return i; } return nums.size(); } };
参考:代码随想录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Solution {public : vector <vector <int >> fourSum(vector <int >& nums, int target) { vector <vector <int >> result; sort(nums.begin(), nums.end()); for (int k = 0 ; k < nums.size(); k++) { if (nums[k] > target && nums[k] >= 0 && target >= 0 ) { break ; } if (k > 0 && nums[k] == nums[k - 1 ]) { continue ; } for (int i = k + 1 ; i < nums.size(); i++) { if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0 && target >= 0 ) { break ; } if (i > k + 1 && nums[i] == nums[i - 1 ]) { continue ; } int left = i + 1 ; int right = nums.size() - 1 ; while (right > left) { if ((long ) nums[k] + nums[i] + nums[left] + nums[right] > target) { right--; } else if ((long ) nums[k] + nums[i] + nums[left] + nums[right] < target) { left++; } else { result.push_back(vector <int >{nums[k], nums[i], nums[left], nums[right]}); while (right > left && nums[right] == nums[right - 1 ]) right--; while (right > left && nums[left] == nums[left + 1 ]) left++; right--; left++; } } } } return result; } };
去重操作优化 原实现的问题 :在找到有效四元组后,先通过while循环跳过相邻重复元素,然后再执行额外的right--和left++,存在冗余操作,可能导致跳过有效解。
优化方案 :直接保存当前找到解时的left和right值,然后跳过所有相同的值,避免冗余的指针移动。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class Solution {public : vector <vector <int >> fourSum(vector <int >& nums, int target) { vector <vector <int >> result; sort(nums.begin(), nums.end()); for (int k = 0 ; k < nums.size(); k++) { if (nums[k] > target && nums[k] >= 0 && target >= 0 ) { break ; } if (k > 0 && nums[k] == nums[k - 1 ]) { continue ; } for (int i = k + 1 ; i < nums.size(); i++) { if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0 && target >= 0 ) { break ; } if (i > k + 1 && nums[i] == nums[i - 1 ]) { continue ; } int left = i + 1 ; int right = nums.size() - 1 ; while (right > left) { long sum = (long ) nums[k] + nums[i] + nums[left] + nums[right]; if (sum > target) { right--; } else if (sum < target) { left++; } else { result.push_back(vector <int >{nums[k], nums[i], nums[left], nums[right]}); int currentLeft = nums[left]; while (right > left && nums[left] == currentLeft) left++; int currentRight = nums[right]; while (right > left && nums[right] == currentRight) right--; } } } } return result; } };
优化效果 :
减少了冗余的指针移动操作
避免了可能跳过有效解的错误
代码逻辑更加清晰直观
#TODO 复习核心内容:转换为两数之和,注意去重操作