三数之和(力扣15)

题目描述

题目链接:力扣icon-default.png?t=M276https://leetcode-cn.com/problems/3sum/

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

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

解法要点

        这也是力扣热门中等难度的算法题,有一题好像是简单题,跟这个解法类似,是找两个数的组合等于目标值。就是先对数组排序,然后头尾指针指向的数字相加,如果比目标值大,右指针左移,比目标值小,左指针右移。至于为啥这么做,你自己那张纸画画想想吧。

        这里稍微难了点,有三个数了,那其实也挺简单,咱们固定一个数,然后对另外俩数做上面的操作,移动的两个数碰到了,固定的那个数就指向下一个。

        有个比较容易出错的坑,就是要去除重复的组合,这样,我们在固定数字循环,和头尾指针移动的时候碰到相同的数字都要直接跳过。跳过的时机有讲究,第一次碰到时不能跳,必须用过后,再碰到,才能跳过,否则会漏掉一些组合。

        比如 -1 -1 2 3,如果碰到 第一个 -1时直接跳到第二个数字,那么你就一个和为 0 的组合都找不着。左右指针移动时也要注意相同的点,相同的数字不能碰见就跳过,但是用过之后一定要跳过。

代码

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ansList = new ArrayList<>();
        if(nums == null){
            return ansList;
        }
        int len = nums.length;
        if(len < 3){
            return ansList;
        }
        // 老规矩,先排序
        Arrays.sort(nums);
       
        // 注意,i的循环范围,最大到 i-3 的下标,后面还得留俩数
        for(int i = 0; i < len-2; i ++){
            int num = nums[i];
            if(num > 0){ //固定的值是三个数中最小的,它都大于0了,后面就不用再试了
                return ansList;
            }

            // 这里必须判断 num == nums[i-1],而不能是 num == nums[i+1],否则会导致相同数字中前面的那些没用到
            if(i > 0 && num == nums[i-1]){
                continue;
            }
            int l = i+1;
            int r = len-1;
            while(l < r){
                int sum = num + nums[l] + nums[r];
                if(sum > 0){
                    r--;
                } else if (sum < 0){
                    l++;
                } else {
                    // 如果满足条件了,还等往下试,因为如果 l 大一点,r 再小一点,也是可能的
                    List<Integer> ans =  Arrays.asList(num, nums[l], nums[r]);
                    ansList.add(ans);
                    // 为了避免重复,碰到相同的数字,我们对 l 取最右,对 r 取最左
                    // 必须放在这里跳过相同数字,因为这里才能确保它们都被用过
                    while(l<r && nums[l] == nums[l+1]){
                        l++;
                    }
                    while(l<r && nums[r] == nums[r-1]){
                        r--;
                    }
                    r--;
                    l++;
                }
            }
        }
        return ansList;
    }
}

现在,关于三数之和这道题,你已经知道得和我一样多了~

本专栏定期更新力扣算法讲解,希望以最容易记忆的方式帮你搞定面试算法题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值