18. 四数之和
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
借用上个博文里三数之和的函数,做了些剪枝
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
int start = 0;
int len = nums.length;
//先排序
Arrays.sort(nums,0,len);
List<List<Integer>> res = new ArrayList<List<Integer>>();
for(;start < len - 3; start++){
if(start > 0 && nums[start] == nums[start - 1])
continue;
int min = nums[start] + nums[start + 1] + nums[start + 2] + nums[start + 3];
int max = nums[start] + nums[len - 1] + nums[len - 2] + nums[len - 3];
if(min > target)
break;
if(max < target)
continue;
int tar = target - nums[start];
List<List<Integer>> tmp = threeSum(nums, start+1,tar);
if(!tmp.isEmpty()){
for(List<Integer> temp : tmp){
temp.add(nums[start]);
Collections.sort(temp);
res.add(temp);
}
}
}
res = new ArrayList<List<Integer>>(new HashSet<List<Integer>>(res));
return res;
}
public List<List<Integer>> threeSum(int[] nums,int p,int target) {
//时间复杂度O(n^2)
List<List<Integer>> res = new ArrayList<List<Integer>>();
int q,k;
if(nums.length - p < 3)
return res;
int initial = p;
for(;p < nums.length - 2; ++p){
q = nums.length - 1;
k = p + 1;
//最外层定一个从左向右遍历
//另两个变量相互夹逼找结果
if(p - 1 >= initial && nums[p] == nums[p - 1])
continue;
int min = nums[p] + nums[p + 1] + nums[p + 2];
int max = nums[p] + nums[q] + nums[q - 1];
if(min > target)
break;
if(max < target)
continue;
while(k < q){
if(nums[p] + nums[q] + nums[k] > target){
--q;
while(q > p + 1 && nums[q] == nums[q + 1])
--q;
}else{
if(nums[p] + nums[q] + nums[k] < target){
++k;
while(k < q && nums[k] == nums[k - 1])
++k;
}else{
List<Integer> tmp = new ArrayList<Integer>();
tmp.add(nums[p]);
tmp.add(nums[k]);
tmp.add(nums[q]);
res.add(tmp);
++k;
--q;
while(k < q && nums[k] == nums[k - 1]&& nums[q] == nums[q + 1])
++k;
}
}
}
}
return res;
}
}