For example, given array S = {-1 0 1 2 -1 -4},
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
【解析】
K Sum问题是一个系列,博客 http://tech-wonderland.NET/blog/summary-of-ksum-problems.html 总结得比较完整,有兴趣可以去看。
作为初学者,我们用最简洁的思路来说一下这道题怎么解。
暴力解决法是每个人都能想到的,三层for循环,时间复杂度是O(n^3),而且还要处理重复的问题,显然不是题目想要的解法。
那能不能降到O(n^2)?排序算法的时间复杂度为O(nlgn),小于O(n^2),那么我们不妨先对数组排个序。
排序之后,我们就可以对数组用两个指针分别从前后两端向中间扫描了,如果是 2Sum,我们找到两个指针之和为target就OK了,那 3Sum 类似,我们可以先固定一个数,然后找另外两个数之和为第一个数的相反数就可以了。
代码不难,先看了再说。
java
public List<List<Integer>> threeSum(int[] nums) {;
List<List<Integer>> result=new ArrayList<List<Integer>>();
if(nums==null||nums.length<3) return result;
sort(nums);
for(int i=0;i<nums.length;i++){
if(i>0&&nums[i-1]==nums[i]) continue;
find(nums,i+1,nums[i],result);
}
return result;
}
public void find(int[] nums,int start,int x, List<List<Integer>> result){
int l=start;
int w=nums.length-1;
while(l<w){
if(x+nums[l]+nums[w]==0){
List<Integer> temp=new ArrayList<Integer>();
temp.add(x);
temp.add(nums[l]);
temp.add(nums[w]);
result.add(temp);
while(l<w&&nums[l]==nums[l+1]) l++;
while(l<w&&nums[w]==nums[w-1]) w--;
l++;
w--;
}else{
if(x+nums[l]+nums[w]<0){
l++;
}
else{
w--;
}
}
}
}
public void sort(int[] nums){
for(int i=1;i<nums.length;i++){
int temp=nums[i-1];
if(i>0&&nums[i-1]>nums[i]){
temp=nums[i];
int j=i-1;
while(j>=0&&temp<nums[j]){
nums[j+1]=nums[j];
j--;
}
nums[j+1]=temp;
}
}
}
注意,对于 num[i],寻找另外两个数时,只要从 i+1 开始找就可以了。
这种写法,可以避免结果集中有重复,因为数组时排好序的,所以当一个数被放到结果集中的时候,其后面和它相等的直接被跳过。
z = nums[i];
if (i > 0 && z == nums[i - 1])// avoid duplicate
continue;
if (z + 3 * max < target) // z is too small
continue;
if (4 * z > target) // z is too large
break;
if (4 * z == target) { // z is the boundary
if (i + 3 < nums.length && nums[i + 3] == z) {
List<Integer> temp = new ArrayList<Integer>();
temp.add(z);
temp.add(z);
temp.add(z);
temp.add(z);
result.add(temp);
}
break;
}
1667



被折叠的 条评论
为什么被折叠?



