leetcode15-三数之和

88 阅读2分钟

题目

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入: nums = [-1,0,1,2,-1,-4]

输出: [[-1,-1,2],[-1,0,1]]

来源:力扣(LeetCode)

链接:leetcode.cn/problems/3s…

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码

public class Leetcode15 {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        // 1。 因为要保证每个结果集里面的元素不完全重复 先排序后在循环中比较与上一次是否相等,会比较简单
        // 2。 排序之后还有一个特性,从小到大排了以后,当我们确定a的值以后,将b从小值往大值遍历时,如果每个b都有对应的c满足题目条件,那么随着b的增加,c
        //     应该在一直减小;所以对于b的从小到大循环,c只需一个指针从大到小移动;这就是常用的双指针
        // 当然,需要注意的时,b不一定有唯一的c对应,所以我们的判断条件时b+c>a,如果不满足,就将b指针+1,这样才可能继续满足这个条件
        Arrays.sort(nums);
        int len = nums.length;
        for(int first = 0;first<len;first++){
            if(first>0 && nums[first]==nums[first-1]){
                // 首先保证不会完全重复
                continue;
            }
            // 确定a,以后 可以确定目标值,即b+c
            int target = -nums[first];
            // c的起始遍历节点
            int third = len-1;
            for (int second = first+1;second<len;second++){
                // 确定b以后 可以开始判断前面提到的逻辑
                if(second>first+1 && nums[second]==nums[second-1]){
                    continue;
                }
                // 当还是满足b+c>target时,需要减小c,直到不满足
                while (second<third && nums[second]+nums[third]>target){
                    third--;
                }
                // 此时两种情况:1. 知道b c重合都还是大于,就没有符合的条件了(此时已经最小了),可以跳出循环了
                if(second==third){
                    break;
                }
                // 2. nums[second]+nums[third]==target,这个就是我们需要找的答案
                if(nums[second]+nums[third]==target){
                    List<Integer> resultItem = new ArrayList<>(3);
                    resultItem.add(nums[first]);
                    resultItem.add(nums[second]);
                    resultItem.add(nums[third]);
                    result.add(resultItem);
                }
                // 第三种情况,nums[second]+nums[third]<target,这种情况就让c变大
            }
        }
        return result;
    }
}

解释

题目核心有两个要点:a+b+c=0 答案中不可以包含重复的三元组

要解决这个题目,有两个重要的方法:

1.排序: 对于第二个条件,排序可以很好的解决,排序之后,当遍历第一层时,如果元素与上一个元素相等,则可以直接跳过(因为与上一个元素的逻辑数组重复)

2.双指针:对于上面的逻辑成立后,其实还是一个0(n3)的复杂度;所以还需要利用到一个特性,从小到大排了以后,当我们确定a的值以后,将b从小值往大值遍历时,如果每个b都有对应的c满足题目条件,那么随着b的增加,c应该在一直减小;所以对于b的从小到大循环,c只需一个指针从大到小移动;这就是常用的双指针;当然,需要注意的时,b不一定有唯一的c对应,所以我们的判断条件时b+c>a,如果不满足,就将b指针+1,这样才可能继续满足这个条件

总结

又是一道双指针经典题目,对于双指针题目;没想到用双指针时,做起来会很吃力;题目遇多+总结后,再做就会思路很顺畅;

引用leetcode里面的一句总结 这个方法就是我们常说的「双指针」,当我们需要枚举数组中的两个元素时,如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法

其实这个题目也是这样,我们首先第一层循环确定a以后;剩下的就是在剩余的有序数组中中确定b和c,可以减少一层复杂度