Leetcode不少题目是成一个体系的,这道题是找四数之和等于四数之和的题,之前还有2Sum和3Sum,我也已经做了题目的小节,可以点开进行查看。
Leetcode #15 3Sum 三数之和 解题小节
Leetcode #1 Two Sum 解题小结
和之前的问题一样,有如下的限制:
1、最终输出的顺序是非降序的(所以我们首先需要排序)
2、不能输出重复的解(所以我们要注意移动)
这道题的解法,从最终的运行时间,我提供的解法应该属于次优级的,也就是说应该有更好的方法,但是我没时间去看。我的4Sum的算法是直接衍生于3Sum的。
我在3Sum里面是这么写的:
1、首先就是排序了,毕竟排序后方便找,也符合题目给的不降序的输出
2、选择一个值作为基准(位置i),然后在这个值后面(i+1)和末尾(n-1)分别初始化两个指针p q 3、判断i p
q位置的值大小是否等于target,如果等于就输出一个(然后随便改变p++或q–),如果小于那么p++,如果大于那么q–。
4、上述过程中一直执行到p==q的时候,那么又回到i,选择下一个基准位置。特别注意: 1、注意i p q的取值范围 2、为了防止重复,在移动第一个
第二个指针的时候,如果遇到移动后和移动前一样,那么记得要做一个移动,直到和上一个取值不一样为止
而在4sum里面我的做法类似,简略说下不同的地方,请对照上面的内容:
1、排序,同3sum
2、在3sum只有一个i基准的情况下,两个循环嵌套,分别为i,和j,对应两个基准值,然后再初始化两个指针p和q,剩下的做法和3sum一样
3、4完全同3sum一样,只是变成i j p q四个位置的和相加就可以
那么4sum同样有防止重复的策略,我的策略同3sum一样,除了q(最后一个)移动的时候不检测,其余的i j q移动的时候,移动的下一位要是一个全新的值,不能移动后值不改变
PS:我代码用的是a b ,解题报告里用的是p q,自己对照就好
那么现在如果推导到K-Sum问题,那么按照这个套路(虽然不一定最优,但是很容易想到也很好啊),做法是:
1、排序
2、前K-2个数使用循环遍历组合
3、最后两个数,在2选择剩余的区间内,设立p q指针,指向首尾,此时如果K个位置的和小于目标值,p++(注意条件4),大于的话 q–,等于的话输出。知道p>=q位置
4、在改变前K-1个的指针时,如果移动后和移动前的值一样,那么要继续移动,直到不一样。。即前K-1个再做++等运算时都必须考虑到4这个条件。
原题
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:
Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
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 class Solution {
/**
* 2sum 3sum的变种版
* */
public List> fourSum(int[] nums, int target) {
List> result=new ArrayList>();
Arrays.sort(nums);
int i,j,a,b,reserve;
for( i=0;i3;i++){
for( j=i+1;j2;j++){
a=j+1;
b=nums.length-1;
reserve=target-nums[i]-nums[j];
while(aif(nums[a]+nums[b]>reserve){
b--;
continue;
}
if(reserve==nums[a]+nums[b]){
ArrayList item=new ArrayList();
item.add(nums[i]);
item.add(nums[j]);
item.add(nums[a]);
item.add(nums[b]);
result.add(item);
}
a++;
while(nums[a]==nums[a-1] && awhile(nums[j]==nums[j+1] && j2){
j++;
}
}
while(nums[i]==nums[i+1] && i3 ){
i++;
}
}
return result;
}
}