您的位置:首页 > 其它

LeetCode 15 3Sum

2016-06-08 00:00 537 查看

3Sum

Given an array
S
of
n
integers, are there elements
a
,
b
,
c
in
S
such that
a
+
b
+
c
= 0? Find all unique triplets in the array which gives the sum of zero.

Note:

Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)

The solution set must not contain duplicate triplets.

For example, given array S = {-1 0 1 2 -1 -4},

A solution set is:
(-1, 0, 1)
(-1, -1, 2)


解题思路:这一道题是2-sum问题的延续,几乎所有人都能想到O(n^3)复杂度的三重循环的判断方法,显然对于较大的序列,三重循环的时间复杂度难以忍受。思路与解决2-sum的方法一致,首先将序列排序,然后拿出一个定值,在该值的基础上,设置两个指针start和end分别从序列的开头和末尾进行遍历判断,若计算结果大于0,则末尾左移。若计算结果小于0,则开头右移。

在上述基础之上,已经可以解决该问题,但是重复性的工作并没有彻底的消除。另外,结果的重复性也没有消除。因此,还需要对下标做一些计算处理。

(1).对于结果已经处于升序状态是有原因的,当我们开始遍历的时候,代码如下:

int start =i+1;
int end = len-1;
int s = nums[i]
;

这样的遍历方式保证了结果按升序排列,可能你会担心会漏掉一些结果,实际上这样的担心是多余的,那些start在 s之前的情况实际上已经被s start end这种情况所包含,因此担心是多余的。

(2).为了解决重复性的问题,当完成一次==0的判断之后,对于nums[start]、nums[end]若有重复值,则让其指针分别++和--。

(3)在第一层循环,对于重复的s值,应该将其跳过,否则会有重复的序列。不必要担心会漏解,因为在前一次循环已经把所有解都计算出来了。

(4).为了保证没有漏解,比如 0、0、-1、-1、0序列,在完成第一判断得到{0,0,0}之后,并完成(2)以后,进行start++、end--操作。

代码如下:

public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> lists=new ArrayList<List<Integer>>();
if(nums.length<=2)return lists;
Arrays.sort(nums);
int len =nums.length;
for (int i = 0; i < len-2; i++) {//len-2已经包含所有情况
if(i>0&&nums[i]==nums[i-1])continue;//这里是i-1与i的判断因为for循环已经i++了
int start =i+1;
int end = len-1;
int s = nums[i];
while(start<end){
Integer[] arr = new Integer[3];
int re = s +nums[start]+nums[end];
if(re>0){
end--;
}else if(re<0){
start++;
}else{
arr[0]=s;
arr[1]=nums[start];
arr[2]=nums[end];
ArrayList<Integer> tr = new ArrayList<Integer>();
tr.add(arr[0]);
tr.add(arr[1]);
tr.add(arr[2]);
lists.add(tr);
while (start < end && nums[start] == nums[start+1]) start++;
while (start < end && nums[end] == nums[end-1]) end--;
start++;//对于同一个s  可能有多个适配的情况; 这个如果放在重复判断之前 会导致漏解比如 -2 0 1 1 2
end--;
}
}
}
return lists;
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: