给你一个由 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
你可以按 任意顺序 返回答案 。
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ans=new ArrayList<List<Integer>>();
int n=nums.length;
Arrays.sort(nums);
if(n<4){
return ans;
}
for(int a=0;a<n-3;a++){
if(a>0 && nums[a]==nums[a-1]){
continue;
}
if((long)nums[a]+nums[a+1]+nums[a+2]+nums[a+3]>target){
break;//剪枝
}
if((long)nums[a]+nums[n-1]+nums[n-2]+nums[n-3]<target){
continue;
}
for(int b=a+1;b<n-2;b++){
if(b>a+1 && nums[b]==nums[b-1]){
continue;
}
if((long)nums[a]+nums[b]+nums[b+1]+nums[b+2]>target){
break;//这里报错因为上面for循环里开始写的是b<n,这里的b+2和b+1越界
}//剪枝
if((long)nums[a]+nums[b]+nums[n-1]+nums[n-2]<target){
continue;
}
int c=b+1;
int d=n-1;
while(c<d){
long sum=nums[a]+nums[b]+nums[c]+nums[d];
if(sum==target){
List<Integer> list=new ArrayList<Integer>();
list.add(nums[a]);
list.add(nums[b]);
list.add(nums[c]);
list.add(nums[d]);
ans.add(list);
while(c<d && nums[c]==nums[c+1]){
c++;
}
c++;
while(c<d && nums[d]==nums[d-1]){
d--;
}
d--;
} else if(sum<target){
c++;
}else{
d--;
}
}
}
}
return ans;
}
}
思路:与前面的三数之和很相似,先对数组进行排序,然后创建一个二重数组来保存最终答案。
当数组中的值小于4个时,直接返回空数组。
然后设置abcd四个下标,a从第一个元素开始到倒数第四个,b从a的下一个开始到倒数第三个;c从b的下一个开始,d从最后一个开始。
其中还有一些剪枝函数,比如当nums[a]+nums[a+1]+nums[a+2]+nums[a+3]>target时,就可以直接跳出循环,因为后面的数都比这四个数大,无论如何也找不到=target的数。其余类似。
最后将符合条件的数添加到数组中,将符合条件的数组添加到二重数组中。