18. 四数之和
解法1(解法2的删减版,当数据过多会超时,写法正确)
package LeetCode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class Solution {
List<List<Integer>>res=new ArrayList<List<Integer>>();
List<Integer>tmp=new ArrayList<Integer>();
public List<List<Integer>> fourSum(int[] nums, int target) {
if(nums==null||nums.length<4) return res;
Arrays.sort(nums);
kSum(4,0,target,nums); //四数之和,target=4
return res;
}
private void kSum(int k,int start,int target,int[]nums){
if (k==0){
if (target==0){ //4个数减了4次恰好等于0
res.add(new ArrayList<Integer>(tmp));
}
}
int len=nums.length;
// if (k>2){ //K从3开始 注意这里K>2,K>3会超时
for (int i = start; i <=len-k ; i++) { //如果数组中一共有6个数,i到4就有四个数的和,i到3就停止遍历(3个数的和) K个元素
if (i>start&&nums[i]==nums[i-1]) continue; //i>start 保证nums[i]==nums[i-1] 不越界
tmp.add(nums[i]); //里面已经有一个i 例:i=-4
kSum(k-1,i+1,target-nums[i],nums) ; //后面找剩下的(3-1)个 target剩下的两个数之和
tmp.remove(tmp.size()-1);
// }
}
// else if(k==2){
// int left=start,right=len-1;
// while (left<right){
// int sum=nums[left]+nums[right];
// if (sum<target){
// do{
// left++; //相当于开始int left=start+1
// }while (left<right&&nums[left]==nums[left-1]); //去重
// }
// else if(sum>target){
// do{right--;}
// while (left<right&&nums[right]==nums[right+1]); //去重
//
// }
// else {
// tmp.add(nums[left]);
// tmp.add(nums[right]);
// res.add(new ArrayList<Integer>(tmp));
// tmp.remove(tmp.size()-1);
// tmp.remove(tmp.size()-1);
// while (left<right&&nums[left]==nums[left+1])left++;
// while (left<right&&nums[right]==nums[right-1])right--;
// left++;
// right--;
// }
// }
// }
}
}
解法2.
package LeetCode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class Solution {
List<List<Integer>>res=new ArrayList<List<Integer>>();
List<Integer>tmp=new ArrayList<Integer>();
public List<List<Integer>> fourSum(int[] nums, int target) {
if(nums==null||nums.length<4) return res;
Arrays.sort(nums);
kSum(4,0,target,nums); //四数之和,target=4
return res;
}
private void kSum(int k,int start,int target,int[]nums){
int len=nums.length;
if (k>2){ //K从3开始 注意这里K>2,K>3会超时
for (int i = start; i <=len-k ; i++) { //如果数组中一共有6个数,i到4就有四个数的和,i到3就停止遍历(3个数的和) K个元素
if (i>start&&nums[i]==nums[i-1]) continue; //i>start 保证nums[i]==nums[i-1] 不越界
tmp.add(nums[i]); //里面已经有一个i 例:i=-4
kSum(k-1,i+1,target-nums[i],nums) ; //后面找剩下的(3-1)个 target剩下的两个数之和
tmp.remove(tmp.size()-1);
}
}else if(k==2){
int left=start,right=len-1;
while (left<right){
int sum=nums[left]+nums[right];
if (sum<target){
do{
left++; //相当于开始int left=start+1
}while (left<right&&nums[left]==nums[left-1]); //去重
}
else if(sum>target){
do{right--;}
while (left<right&&nums[right]==nums[right+1]); //去重
}
else {
tmp.add(nums[left]);
tmp.add(nums[right]);
res.add(new ArrayList<Integer>(tmp));
tmp.remove(tmp.size()-1);
tmp.remove(tmp.size()-1);
while (left<right&&nums[left]==nums[left+1])left++;
while (left<right&&nums[right]==nums[right-1])right--;
left++;
right--;
}
}
}
}
}