在leetcode里有一类题目,可以统称为K Sum 问题,大意就是:给出一个数组,一个目标值,要求你找出这个数组中所有的组合,满足:这k个数的组合之和为target值。
举个栗子(four sum):
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)
其实所有的解法都可以从twosum得出,先给出twosum的解法:
1. 先给数组nums排序;
2. 放两个指针,一个在数组头,一个在数组尾部;
3. 判断两数之和是否为target,如果是,保存此组合;
4. 如果不是
i: 小于target,头指针往尾部方向移动一格;
ii.大于target,尾部指针往头部方向移动一格;
为了避免麻烦的重复答案的讨论,我用来一个HashSet,来保证最终结果的唯一性。
注意:HashSet 可以判断List在set中的唯一性,却无法判断int[]在set中的唯一性。所以代码中如果把temp设为了int[], 则结果会出现重复的问题。
twosome代码如下:
public List<List<Integer>>twoSum(int[]nums,int target){
List <List<Integer>>L=new ArrayList<List<Integer>>();
List<Integer>l;
Arrays.sort(nums);
HashSet<List<Integer>>result=new HashSet<List<Integer>>();
List<Integer>temp;
int i=0,j=nums.length-1;
while(i<j){
if(nums[i]+nums[j]==target){
temp=new ArrayList<Integer>();
temp.add(nums[i]);
temp.add(nums[j]);
if(!result.contains(temp)){
result.add(temp);
L.add(temp);
}
i++;
j--;
}
else if(nums[i]+nums[j]<target)
i++;
else j--;
}
return L;}
threeSum 和 fourSum的方法就是多几层循环,也就是先把最开头的几个数定了,比如three Sum中,先定好第一个数,就讲此问题退化成了一个twoSum的问题。
但要注意的是:如果想保证所耗时间尽可能的少,还需在头指针加入一个判断,判断此头指针之前有没有已经讨论过了
ThreeSum代码如下:
public List<List<Integer>>threeSum(int[]nums,int target){
List <List<Integer>>L=new ArrayList<List<Integer>>();
List<Integer>l;
List<Integer>temp;
HashSet<List<Integer>>result=new HashSet<List<Integer>>();
int j,k;
Arrays.sort(nums);
for(int i=0;i<nums.length-2;i++){
if(i!=0&&nums[i]==nums[i-1])continue;
j=i+1;
k=nums.length-1;
while(j<k){
if(nums[i]+nums[j]+nums[k]==target){
// System.out.println("find one");
temp=new ArrayList<Integer>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[k]);
if(!result.contains(temp)){
result.add(temp);
L.add(temp);}
j++;
k--;
}
else if(nums[i]+nums[j]+nums[k]<target){
j++;
}
else k--;
}
}
return L;
}
FourSum代码如下:
public List<List<Integer>> fourSum(int[] nums, int target) {
List <List<Integer>>L=new ArrayList<List<Integer>>();
List<Integer>l;
Arrays.sort(nums);
int k,w;
ArrayList<Integer>temp;
HashSet<List<Integer>>result=new HashSet<List<Integer>>();
for(int i=0;i<nums.length-3;i++){
if(i!=0&&nums[i]==nums[i-1])continue;
for(int j=i+1;j<nums.length-2;j++){
if(j!=i+1&&nums[j]==nums[j-1])continue;
// System.out.println("ff");
k=j+1;
w=nums.length-1;
while(k<w){
if(nums[i]+nums[j]+nums[k]+nums[w]==target){
temp=new ArrayList<Integer>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[k]);
temp.add(nums[w]);
if(!result.contains(temp)){
result.add(temp);
L.add(temp);}
k++;
w--;
}
else if(nums[i]+nums[j]+nums[k]+nums[w]<target){
k++;
}
else w--;
}
}
}
return L;
}