刷题日记——三数之和

33 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 22 天,点击查看活动详情

第15题. 三数之和

力扣题目链接(opens new window)

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

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

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]

思路

看到这题首先我也是想到要用哈希法,但是基本的思路写好了以后发现怎么都不对,原来又漏掉了题目中的条件:不重复的三元组。所以还要在原有的基础上去重,但是我想了一下,去重会很麻烦,所以就没有继续写,所以我们来开拓个新的方法吧。

看了代码随想录的题解后,我有了大致方向,这道题果然还是得用双指针。

首先要把对这个数组进行排序,然后我们就可以开始遍历了,因为排过序,所以第一个数一定是最小的,这时候我们判断:如果这个数大于零,那么这个数组就一定不成立了,这时候就可以直接返回。判断然这个后,还有一个重要点就是i和左右指针,如果nums[i]==nums[i-1]就可以判断a是不是重复了,但是不能与i+1比较,因为我们只能规避过去犯过的错,而不能预知未来会犯的错。就是大概这个意思。

关于指针,如果三数之和大于零,就可以右指针左移,把最大的数变小,如果三数之和大于零,就可以左指针右移,把最小的数变大。

按照上面的思路,就可以写出代码啦。

解法

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