每日打卡:三数之和

511 阅读2分钟

这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

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

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

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

原文链接

!!!说实话,第一眼看到这到题的时候我是真的头痛,三个数相加等于零?之前我们有做过两数之和的题,那我们一样就可以看出来双指针吗!这个三个数,好家伙,三指针吗?这我也不会啊?

俗话说的好,只要我们不会一道题的时候,我们就去找他的暴解,再从暴解中寻找我们的正确答案

我们从图里看一下我们暴力是怎么解决的

08A135CF62D74203652EE708DD851E17.jpg

三个循环嵌套加一个判断,想用它去做题,真的是痴心妄想,但是我们在这个解法中我们可以想到什么?

为什么暴力不可取,因为我们会重复的判断很多已经判断过的值,之后再去想一想我们的两数之和,先对数组排序,在进行双指针从两端移动,那我们三数之和,我们在中间再去添加一个指针,是不是就可以了?

那中间那个指针我们怎么去移动呢?

B47CC86EB50A0B7C55B33D857F6638B4.jpg

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

这就是我们的代码,但是它出错了,为什么呢?我们再去看一下题干,就是我们重复的三元我们是不需要的,那我们就需要去做一个去重的操作,那我们这一步填到哪里呢?

就是在我们指针移动的时候,如果我们指针移动到下一个元素是重复的时候我们就继续向前移动

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        //排序
        Arrays.sort(nums);
        List<List<Integer>> res=new ArrayList<>();
        //这里-2的原因是因为我们是三个指针我们要留两个空位置
        for(int k=0;k<nums.length-2;k++){
            //先确定一下首位元素,如果最小的比0大或者最大的比0小,我们就不需要搞这些了
            if(nums[k]>0||nums[nums.length-1]<0) break;
            //对我们的起始位置K进行去重操作
            if(k>0 && nums[k]==nums[k-1]) continue;
            //定义左指针
            int i=k+1;
            //定义右指针
            int j=nums.length-1;
            while(i<j){
                int sum=nums[k]+nums[i]+nums[j];
                if(sum<0){
                    //左指针右移,去重
                    while(i<j&&nums[i]==nums[++i]);
                }else if(sum>0){
                    //右指针左移,去重
                    while(i<j&&nums[j]==nums[--j]);
                }else{
                    //添加到集合
                    res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));
                    //两边指针向中间移动
                    while(i<j&&nums[i]==nums[++i]);
                    while(i<j&&nums[j]==nums[--j]);
                }
            }
        }
        return res;
    }
}

!!!注意:如果有看完的自己写的小伙伴,注意这个i++--i 如果我们使用的是i++ 我们获取的还是i的值,他就会出问题