题目
给出一个有n个整数的数组S,在S中找到三个整数a, b, c,找到所有使得a + b + c = 0的三元组。
样例
如S = {-1 0 1 2 -1 -4}, 你需要返回的三元组集合的是:
(-1, 0, 1)
(-1, -1, 2)
注意
Java Code
Java Code
Java Code
Python Code
在三元组(a, b, c),要求a <= b <= c。
结果不能包含重复的三元组。
解题:
法一:直接暴力,时间复杂度是O(N3)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class Solution { /** * @param numbers : Give an array numbers of n integer * @return : Find all unique triplets in the array which gives the sum of zero. */ public ArrayList<ArrayList<Integer>> threeSum(int[] numbers) { // write your code here ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(); if(numbers == null || numbers.length<3) return result; for(int i = 0;i< numbers.length - 2 ; i++){ ArrayList<Integer> path = new ArrayList<Integer>(); for(int j = i+1;j < numbers.length - 1 ; j++){ for(int k = j+ 1 ; k < numbers.length ; k++) if(numbers[i] + numbers[j] + numbers[k] == 0 ){ path = sort3(numbers[i],numbers[j],numbers[k]); if(result.contains(path)==false) result.add(path); } } } return result; } public ArrayList<Integer> sort3(int a,int b,int c){ ArrayList<Integer> path = new ArrayList<Integer>(); if(a>b){ int tmp = a; a = b; b = tmp; } if(c<=a){ path.add(c); path.add(a); path.add(b); }else if(c>=b){ path.add(a); path.add(b); path.add(c); }else{ path.add(a); path.add(c); path.add(b); } return path; } }
在运行到94%的测试数据的时候WA,下面答案只是第三个和第二个的顺序不一样,怎么能就算错了?
法二:
将原数组存放中ArrayList中,通过判断 -(nums[i]+nums[j]) 是否在ArrayList中,少了第三个for循环,时间复杂度O(N2)增加了空间发杂度O(N)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class Solution { /** * @param numbers : Give an array numbers of n integer * @return : Find all unique triplets in the array which gives the sum of zero. */ public ArrayList<ArrayList<Integer>> threeSum(int[] numbers) { // write your code here ArrayList<Integer> path = new ArrayList<Integer>(); ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(); if(numbers == null || numbers.length<3) return result; ArrayList<Integer> nums = new ArrayList<Integer>(); for(int i = 0 ;i < numbers.length ; i++) nums.add(numbers[i]); for(int i = 0;i< nums.size() - 2;i++){ for(int j = i+ 1; j<nums.size() -1;j++){ int sum = -((Integer)nums.get(i) + (Integer)nums.get(j)); if(nums.contains(sum) && nums.indexOf(sum) !=j && nums.indexOf(sum) !=i){ path = sort3(sum,nums.get(i),nums.get(j)); if(result.contains(path)==false) result.add(path); } } } return result; } public ArrayList<Integer> sort3(int a,int b,int c){ ArrayList<Integer> path = new ArrayList<Integer>(); if(a>b){ int tmp = a; a = b; b = tmp; } if(c<=a){ path.add(c); path.add(a); path.add(b); }else if(c>=b){ path.add(a); path.add(b); path.add(c); }else{ path.add(a); path.add(c); path.add(b); } return path; } }
但是运行还是出现上面的情况
法三:
三个数的和基础还是两个数的和、两个数的和||,a+b+c = 0,等价于a+b = -c,这样就和两个数的和|| 很类似,当然也可以参考两个数的和I求解。
先对数组排序,排序后的数组,定义其实节点i,然后对i+1 到len内的所有节点进行两端遍历,这里利用二分查找的思想,
设两端的两个下标是left 和right ,显然 sum=nums[i] + nums[left] + nums[right] >0时候 ,right--,小于0的时候left++,等于0的时候就是答案。时间复杂度O(NlogN)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class Solution { /** * @param numbers : Give an array numbers of n integer * @return : Find all unique triplets in the array which gives the sum of zero. */ public ArrayList<ArrayList<Integer>> threeSum(int[] numbers) { // write your code here ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(); if(numbers == null || numbers.length<3) return result; Arrays.sort(numbers); for(int i = 0;i<numbers.length; i++){ int left = i+ 1; int right = numbers.length - 1; while(left < right){ int sum = numbers[i] + numbers[left] + numbers[right]; ArrayList<Integer> path = new ArrayList<Integer>(); if(sum==0){ path.add(numbers[i]); path.add(numbers[left]); path.add(numbers[right]); if(result.contains(path)==false) result.add(path); left++; right--; }else if(sum>0){ right--; }else{ left++; } } } return result; } }
总耗时: 1094 ms
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
class Solution: """ @param numbersbers : Give an array numbersbers of n integer @return : Find all unique triplets in the array which gives the sum of zero. """ def threeSum(self, numbers): # write your code here result = [] if numbers == None or len(numbers) < 3: return result numbers.sort() numlen = len(numbers) for i in range(numlen): left = i + 1 right = numlen - 1 while left < right: sum = numbers[i] + numbers[left] + numbers[right] if sum==0: path = [numbers[i],numbers[left],numbers[right]] if path not in result: result.append(path) left +=1 right -=1 elif sum>0: right -=1 else: left +=1 return result
总耗时: 195 ms