力扣 18 四数之和
18. 四数之和
给你一个由
n
个整数组成的数组 nums
,和一个目标值 target
。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]]
(若两个四元组元素一一对应,则认为两个四元组重复):0 <= a, b, c, d < n
a
、b
、c
和d
互不相同nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]
提示:
1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109
先理解最接近的三数之和(尤其是后面的大神解法)。
一、排序
将nums排序
二、a,b去重
1 for(int i=0;i<len;i++){ 2 if(i==0||nums[i]!=nums[i-1]) 3 for(int j=i+1;j<len;j++){ 4 if(j==i+1||nums[j]!=nums[j-1]){
三、循环和双指针
先用i和j 循环a和b的下标,接下来那么l和r就是c,d的,刚开始l在最左边,r在最右边,判断当前值tmp,
tmp>target,说明当前和过大了,应该让tmp减小,所以r左移,r--
tmp<target,说明当前和过小了,应该让tmp增大,所以l右移,l++
tmp==target,记录当前abcd,l++同时r--
四、c,d去重
1 if(tmp==target){ 2 3 res.push_back({nums[i],nums[j],nums[l],nums[r]}); 4 5 if((nums[r]==nums[r-1])||(nums[l]==nums[l+1])){ 6 while(r>l&&(nums[r]==nums[r-1])) 7 r--; 8 while(r>l&&(nums[l]==nums[l+1])) 9 l++; 10 } 11 else 12 r--;l++; 13 14 15 }
五、代码
1 class Solution { 2 public: 3 vector<vector<int>> fourSum(vector<int>& nums, int target) { 4 vector<vector<int>> res; 5 sort(nums.begin(),nums.end()); 6 int len=nums.size(); 7 for(int i=0;i<len;i++){ 8 if(i==0||nums[i]!=nums[i-1]) 9 for(int j=i+1;j<len;j++){ 10 if(j==i+1||nums[j]!=nums[j-1]){ 11 /*i和j就是a 和b的下标,那么l和r就是c,d的*/ 12 int r=len-1; 13 int l=j+1; 14 while(l<r&&r>j){ 15 double tmp=((double)nums[i]+nums[j]+nums[l]+nums[r]);//测试数据会有四个10^9相加,需要先强转double 16 if(tmp>target){ 17 r--; 18 continue; 19 } 20 if(tmp<target){ 21 l++; 22 continue; 23 } 24 if(tmp==target){ 25 26 res.push_back({nums[i],nums[j],nums[l],nums[r]}); 27 28 if((nums[r]==nums[r-1])||(nums[l]==nums[l+1])){ 29 while(r>l&&(nums[r]==nums[r-1])) 30 r--; 31 while(r>l&&(nums[l]==nums[l+1])) 32 l++; 33 } 34 else 35 r--;l++; 36 37 38 } 39 40 41 } 42 } 43 } 44 } 45 return res; 46 } 47 };