# 三数之和 (opens new window)

  • 难度:Medium
  • 标签:排序 双指针

# 刷题思路

  • [x] 排序+双指针夹逼
  • [x] 排序+双指针夹逼(复用twoSum版本)

# 方法 1 排序+双指针夹逼

  • 复杂度:
    • 时间 O(N^2). 排序 O(nlogn) + 遍历*左右指针的夹逼 O(n^2).
    • 空间 O(1)
  • 结果:
    • 执行用时:148 ms, 在所有 JavaScript 提交中击败了97.64%的用户
    • 内存消耗:47.7 MB, 在所有 JavaScript 提交中击败了30.77%的用户
var threeSum = function(nums) {
    const res = []
    if (!nums || nums.length < 3) return res
    nums = nums.sort((a,b) => a-b)
    for (let i=0, len=nums.length; i<len && nums[i]<=0; i++) { // 最左值大于 0 时,后续已无解
        if (i>0 && nums[i]===nums[i-1]) continue // 重复则跳过
        let [left, right] = [i+1, len-1]
        while (left < right) {
            const tmp = nums[i] + nums[left] + nums[right]
            if (tmp === 0) {
                res.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 (tmp < 0) {
                left++
            } else {
                right--
            }
        }
    }
    return res
};

# 方法 2 排序+双指针夹逼(复用twoSum版本)

  • 复杂度:
    • 时间 O(N^2).同上
    • 空间 O(N) 计算 twoSum 时借助了与结果数量相同的额外空间,最好情况即无结果为, 最坏情况结果亦小于N, 故 O(N).
  • 结果:
    • 执行用时:164 ms, 在所有 JavaScript 提交中击败了78.23%的用户
    • 内存消耗:48.3 MB, 在所有 JavaScript 提交中击败了12.34%的用户
var threeSum = function(nums) {
    if (!nums || nums.length<3) return []
    nums.sort((a,b) => a-b)
    const res = []
    for (let i=0, len=nums.length; i<len && nums[i]<=0; i++) {
        if (i>0 && nums[i]===nums[i-1]) continue
        const tmpArr = twoSum(nums, i+1, 0-nums[i])
        for (let j=0; j<tmpArr.length; j++) res.push([nums[i], ...tmpArr[j]])
    }
    return res
};

function twoSum (nums, start, target) {
    let [left, right] = [start, nums.length-1]
    const res = []
    while (left < right) {
        const tmp = nums[left] + nums[right]
        if (tmp === target) {
            res.push([nums[left], nums[right]])
            while (left<right && nums[left]===nums[left+1]) left++
            while (left<right && nums[right]===nums[right-1]) right--
            ;[left, right] = [left+1, right-1]
        } else if (tmp < target) {
            left++
        } else {
            right--
        }
    }
    return res
}

JS刷题记录 Leetcode-js (opens new window) 每周都会更新刷题心得或者题解, 你的点赞或 star 都将助力我产出更好内容~