您的位置:首页 > 其它

Leetcode #18 4Sum 四数之和 解题小节+K-Sum思想

2016-03-20 20:15 441 查看

1题目理解

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,自己对照就好

1.5 K-Sum

那么现在如果推导到K-Sum问题,那么按照这个套路(虽然不一定最优,但是很容易想到也很好啊),做法是:

1、排序

2、前K-2个数使用循环遍历组合

3、最后两个数,在2选择剩余的区间内,设立p q指针,指向首尾,此时如果K个位置的和小于目标值,p++(注意条件4),大于的话 q–,等于的话输出。知道p>=q位置

4、在改变前K-1个的指针时,如果移动后和移动前的值一样,那么要继续移动,直到不一样。。即前K-1个再做++等运算时都必须考虑到4这个条件。

2 原题

原题

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)


3 AC解

public class Solution {
/**
* 2sum 3sum的变种版
* */
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> result=new ArrayList<List<Integer>>();
Arrays.sort(nums);
int i,j,a,b,reserve;
for( i=0;i<nums.length-3;i++){
for( j=i+1;j<nums.length-2;j++){
a=j+1;
b=nums.length-1;
reserve=target-nums[i]-nums[j];
while(a<b){
if(nums[a]+nums[b]>reserve){
b--;
continue;
}
if(reserve==nums[a]+nums[b]){
ArrayList<Integer> item=new ArrayList<Integer>();
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] && a<b ){
a++;
}

}
while(nums[j]==nums[j+1] && j<nums.length-2){
j++;
}
}
while(nums[i]==nums[i+1] && i<nums.length-3 ){
i++;
}
}
return result;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: