[Leetcode] 3Sum
这道题目实际上有非常好的O(N^2)的解法。
关键是利用了2sum的线性解法
public class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> res = new LinkedList<List<Integer>>(); if(nums==null||nums.length==0) return res; Arrays.sort(nums); for(int i=0;i<nums.length-2;i++){ if(i!=0&&nums[i-1]==nums[i]) continue; int sum2 = 0- nums[i]; //search for another two; int left = i+1; int right = nums.length-1; while(left<right){ int tmp = nums[left]+nums[right]; if(tmp==sum2){ List<Integer> listone = new LinkedList<Integer>(); listone.add(nums[i]); listone.add(nums[left]); listone.add(nums[right]); Collections.sort(listone); res.add(listone); left++; right--; while(left<right&&nums[left]==nums[left-1]){ left++; } while(left<right&&nums[right]==nums[right+1]){ right--; } } else if(tmp < sum2){ left++; }else{ right--; } } } return res; } }
问题非常清楚,这里需要注意的是:我们不能使用剪枝策略,而是应该遍历所有的没有重复元素的三元组。
1 public class Solution { 2 public List<List<Integer>> threeSum(int[] nums) { 3 Arrays.sort(nums); 4 boolean flag=false; 5 List<List<Integer> > res=new LinkedList<List<Integer> >(); 6 for(int i=0;i<nums.length;i++){ 7 if(flag) break; 8 int num1=nums[i]; 9 if(i>0){ 10 if(num1==nums[i-1]){ 11 continue; 12 } 13 } 14 for(int j=i+1;j<nums.length;j++){ 15 if(flag) break; 16 int num2=nums[j]; 17 if(j>i+1){ 18 if(num2==nums[j-1]){ 19 continue; 20 } 21 } 22 for(int k=j+1;k<nums.length;k++){ 23 int num3=nums[k]; 24 if(k>j+1){ 25 if(num3==nums[k-1]){ 26 continue; 27 } 28 } 29 int sum = num1 + num2 + num3; 30 /* 31 the pruning method is wrong, such as -2,-1,0,1,2,3 32 -2+2+3>0,how ever -1+0+1 is missed!! 33 if(sum>0){ 34 flag=true; 35 break; 36 } 37 */ 38 if(sum==0){ 39 List<Integer> listone=new ArrayList<Integer>(); 40 listone.add(num1); 41 listone.add(num2); 42 listone.add(num3); 43 res.add(listone); 44 } 45 } 46 } 47 } 48 return res; 49 } 50 }
上面的注释处举例说明了为什么不能根据sum的大小进行剪枝的原因。