Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note: The solution set must not contain duplicate quadruplets.
For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0. A solution set is: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]有两种方法:一种是通过三个循环求解;另一种是用两位数的和,推到三位数的和,再推至四位数的和。
代码一:
public List<List<Integer>> fourSum2(int[] num,int target){
ArrayList<List<Integer>> ans = new ArrayList<>();
if(num.length<4)
return ans;
Arrays.sort(num);
for(int i=0;i<num.length-3;i++){
if(i>0 && num[i]==num[i-1])
continue;
for(int j=i+1;j<num.length-2;j++){
if(j>i+1 && num[j]==num[j-1])
continue;
int low=j+1,high=num.length-1;
while(low<high){
int sum = num[i]+num[j]+num[low]+num[high];
if(sum==target){
ans.add(Arrays.asList(num[i],num[j],num[low],num[high]));
while(low<high && num[low]==num[low+1])
low++;
while(low<high && num[high]==num[high-1])
high--;
low++;
high--;
}else if(sum<target){
low++;
}else{
high--;
}
}
}
}
return ans;
}
代码二:
public List<List<Integer>> fourSum(int[] nums, int target) {
ArrayList<List<Integer>> ans = new ArrayList<>();
if(nums == null || nums.length<4)
return ans;
Arrays.sort(nums);
int max = nums[nums.length-1];
if(4*nums[0] > target || 4*max<target)
return ans;
for(int i=0;i<nums.length-3;i++){
int z = nums[i];
if(i>0 && nums[i]==nums[i-1])
continue;
if(z+3*max <target)
continue;
if(4*max<target)
break;
if(4*max==target){
if(i+3<nums.length && nums[i+3]==z){
ans.add(Arrays.asList(z,z,z,z));
}
break;
}
threeSumForFourSum(nums,target-z,i+1,nums.length-1,ans,z);
}
return ans;
}
public void threeSumForFourSum(int[] nums,int target,int low,int high,ArrayList<List<Integer>> ans,int z1){
if(low+1>=high)
return;
int max = nums[high];
if(3*nums[low]>target || 3*max<target)
return;
for(int i=low;i<high-1;i++){
int z=nums[i];
if(i>low && nums[i]==nums[i-1]){
continue;
}
if(z+2*max<target){
continue;
}
if(3*z>target){
break;
}
if(3*z==target){
if(i+1<high && nums[i+2]==z){
ans.add(Arrays.asList(z1,z,z,z));
}
break;
}
twoSumForFourSum(nums,target-z,i+1,high,ans,z1,z);
}
}
public void twoSumForFourSum(int[] nums,int target,int low,int high,ArrayList<List<Integer>> ans,int z1,int z2){
if(low>=high)
return;
if(2*nums[low]>target || 2*nums[high] < target){
return;
}
while(low<high){
int sum=nums[low]+nums[high];
if(sum == target){
ans.add(Arrays.asList(z1,z2,low,high));
while(low<high && nums[low]==nums[low+1])
low++;
while(low<high && nums[high]==nums[high-1])
high--;
}else if(sum > target){
high--;
}else{
low++;
}
}
return;
}