15. 3Sum


class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> res = new ArrayList();
        for(int i = 0; i < nums.length - 2; i++){
            if(i > 0 && nums[i] == nums[i-1]) continue;
            if(nums[i] > 0) return res;
            int lo = i+1, hi = nums.length - 1, sum = -nums[i];
            while(lo < hi){
                int cur = nums[lo] + nums[hi];
                if(cur == sum) {
                    res.add(Arrays.asList(nums[i], nums[lo], nums[hi]));
                    while(lo < hi && nums[lo+1] == nums[lo]) lo++;
                    while(lo < hi && nums[hi-1] == nums[hi]) hi--;
                    lo++;
                    hi--;
                }
                else if(cur < sum) lo++;
                else hi--;
            }
        }
        return res;
    }
}


 

我看这个解答,一开始反复卡在左边界lo为什么==i+1,说是为了避免重复。

后来举例子【-4,-3,1,7】,-4能和-3和7成对,到了-3,如果从0开始,就会也形成-4,-3和7,这样就重复了。所以每次左边界都要从i+1开始

或者这样理解,i是可能解的左下标,lo是中间,hi是右边,所以lo = i + 1

3sum就是固定一个数,剩下就是一个2sum,但题目要求不能有重复triplets出现,所以需要去重

具体方法是先对数组排序,i代表合适解的左下表,所以是i < nums.length - 2, 从下标1开始如果和前面重复就continue,然后如果nums[ i ] > 0就break,因为后面数都比他大不可能还有解。

然后就是具体情况,lo和hi和target设置好,如果lo+hi == target就是一个解,然后左右向中间靠拢,这里也要考虑重复元素,排除重复后更新lo和hi

最后返回即可。

原文地址:https://www.cnblogs.com/wentiliangkaihua/p/10328976.html