【leetcode】15. 三数之和


在这里插入图片描述

🚀题目

leetcode原题链接

给你一个包含 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]]

示例 2:
输入:nums = []
输出:[]

示例 3:

输入:nums = [0]
输出:[]

提示:

0 <= nums.length <= 3000
-105 <= nums[i] <= 105

💥leetcode代码模板

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {

};

🚀思路

在这里插入图片描述
双指针法:

  • 首先对数组进行排序

  • 如果排序后第一个元素就大于0,那么不可能存在三数之和为0,返回空数组

  • 顺序遍历数组的每一项nums[i],每一个nums[i]都可以有可能和它之后的2个数字组合,所以定义一个left = nums[i+1] right = nums[nums.length - 1]

  • 只要left < right 就执行判断三个数的和的操作,只有3种情况:

    • nums[i] + left + right === 0,将三个数添加到结果数组里。

    • nums[i] + left + right < 0,和偏小,说明left的值小了(因为数组升序),left++

    • nums[i] + left + right > 0,和偏大,说明right的值大了(因为数组升序),right--

按照上面思路写出以下代码:

var threeSum = function(nums) {
    let ans = [] , len = nums.length
    nums.sort((a,b) => a - b)   // 排序

    if(len === 0 || nums[0] > 0) return ans // 数组为空或排序后第一项就为0,返回[]

    for(let i = 0 ; i < len ; i++){
        let left = i + 1 , right = len - 1

        while(left < right){
            if(nums[i] + nums[left] + nums[right] === 0) {  // 等于0
                ans.push([nums[i] , nums[left] , nums[right]])
                left++
                right--
            }else if(nums[i] + nums[left] + nums[right] < 0){    // 小于0
                left++
            }else{  // 大于0
                right--
            }
        }
    }

    return ans
};

但是上面的代码还没执行去重操作,所以示例1得到了以下结果

[-1,0,1,2,-1,-4]    // 输入
[-4,-1,-1,0,1,2]    // 排序后
[[-1,-1,2],[-1,0,1],[-1,0,1]]    // 输出
  • 上面的三种情况下的操作做完之后,还要各自执行去重的操作,因为题目要求答案中不能包含重复的三元组。

  • 首先看left right的去重方式,当i确定下来之后,对于相同的元素,leftright都只能取一次。索引下次再遇到相同元素时要越过去。

  • 去重时要遵循一个原则,那就是左指针遇到重复取最左,右指针遇到重复取最右。比如:

[-2, -2, -2, -4, -4, -4, -5, -5, 0(i), 0(left), 0, 1, 1, 3, 4, 4(right)]指针位置标记在数组中,此时right可以取到0,如果是:

[-2, -2, -2, -4, -4, -4, -5, -5, 0(i), 0, 0(left), 1, 1, 3, 4, 4(right)]

即left去重时取的是重复元素的最右边元素,那么right没有机会取到0,这样就遗漏了0,0,0的情况。

💻代码

在这里插入图片描述

var threeSum = function(nums) {
    let ans = [] , len = nums.length
    nums.sort((a,b) => a - b)   // 排序

    if(len === 0 || nums[0] > 0) return ans // 数组为空或排序后第一项就为0,返回[]

    for(let i = 0 ; i < len ; i++){
        let left = i + 1 , right = len - 1

        // i去重,不能nums[i] === nums[i-1],会漏掉-1,-1,2这种情况
        if(i > 0 && nums[i] === nums[i-1]) continue

        while(left < right){
            if(nums[i] + nums[left] + nums[right] === 0) {  // 等于0
                ans.push([nums[i] , nums[left] , nums[right]])
                // 去重
                while(left < right && nums[left] === nums[left + 1]) left++
                while(left < right && nums[right] === nums[right-1]) right--
                left++
                right--
            }else if(nums[i] + nums[left] + nums[right] < 0){    // 小于0
                left++
                // 去重
                while(left < right && nums[left] === nums[left - 1]) left++
            }else{  // 大于0
                right--
                // 去重
                while(left < right && nums[right] === nums[right+1]) right--
            }
        }
    }

    return ans
};

🍪总结

这道题用双指针时需要注意去重的方式,遵循某指针去重时不影响其他指针取到值的原则。


我 是 c o n e r , 请 别 关 注 我 的 专 栏 , 本 系 列 文 章 为 个 人 刷 题 记 录 ( 偷 偷 自 己 卷 🤤 ) : \textcolor{green}{我是coner,请别关注我的专栏,本系列文章为个人刷题记录(偷偷自己卷🤤):} coner🤤leetcode题解js

每 天 更 新 l e e t c o d e 题 目 的 j s 题 解 🚀 🚀 🚀 \textcolor{green}{每天更新leetcode题目的js题解🚀🚀🚀} leetcodejs🚀🚀🚀

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端corner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值