F_G

许多问题需要说清楚就可以&&走永远比跑来的重要

导航

[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的大小进行剪枝的原因。

 

posted on 2015-08-12 20:21  F_G  阅读(195)  评论(0编辑  收藏  举报