leetcode 15 三数之和

原题点这里

取三个数,使和为0,输出所有的组合。各个组合之间不能重复。

这是个稍微复杂一点的逻辑题。它要求所有的组合不能重复。我们很容易想到三个循环嵌套,分别取三个数,判断加和是否为0,如果为0,判断是否重复。其复杂度为n^3.

public static List<List<Integer>> threeSum(int[] nums) {
        HashSet<Node15> all = new HashSet<>();
        int n = nums.length;
        List<List<Integer>> ansList=new ArrayList<>();
        int ans = 0;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                //if(i==j) continue;

                for(int k=j+1;k<n;k++){
                    //if(j==k||i==k) continue;

                    if(nums[i]+nums[j]+nums[k]==0){
                        Node15 t = new Node15(nums[i],nums[j],nums[k]);
                        if(all.contains(t)) continue;
                        else
                            all.add(t);
                        System.out.println("=================================");
                       System.out.println(i+":"+nums[i]+"
"+j+":"+nums[j]+"
"+k+":"+nums[k]);
                        List<Integer> tmp= new ArrayList<>();
                        tmp.add(i);
                        tmp.add(j);
                        tmp.add(k);
                        ansList.add(tmp);
                        ans++;
                    }
                }
            }
        }
        //System.out.println(ans);
        return ansList;
    }
View Code

这样的话超时了。我们想办法优化一下。

1 重复组合的去除。我们可以不用set来去除重复项。我们对数据进行排序。然后选择一个开始遍历。选择一个数nums[i],如果nums[i]==nums[i-1],因为我们数组进行过排序,所以这个数字一定是最小值。那么同一个最小值,不重复的组合必须是剩余的两个数不同。所以我们只取一次即可。我们只要保证剩余的两个数,我们只取不同组合即可。我们使用两个指针,l=i+1,r=len-1.分别指向较小的数,和最大值。

如果 nums[i]+nums[l]+mums[r]=0,这就是一个可选的组合。然后判断,如果nums[l+1]==nums[l],我们跳过nums[l+1],以此类推。对nusm[r]和nums[r-1]也做同样的处理。

public static List<List<Integer>> threeSum2(int[] nums) {

        List<List<Integer>> ansList = new ArrayList<>();

        Arrays.sort(nums);
        int len = nums.length;
        for(int i=0;i<len;i++){
            if(nums[i]>0) break;
            if(i>0&&nums[i]==nums[i-1]) continue;
            int l = i+1;
            int r = len-1;
            while(l<r){
                int ans = nums[i]+nums[l]+nums[r];
                if(ans==0){
                    ansList.add(Arrays.asList(nums[i],nums[l],nums[r]));
                    while(l<r&&nums[l+1]==nums[l])l++;
                    while(l<r&&nums[r-1]==nums[r])r--;
                    l++;
                    r--;
                }
                else if(ans>0) r--;
                else if(ans<0) l++;

            }
        }

        //System.out.println(ans);
        return ansList;
    }
View Code
原文地址:https://www.cnblogs.com/superxuezhazha/p/12875017.html