LeetCode16、 最接近的三数之和

50 阅读1分钟

LeetCode 系列记录我学习算法的过程。

持续创作,加速成长!这是我参与「掘金日新计划 6 月更文挑战」的第 15 天,点击查看活动详情

题目

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

示例:

输入: nums = [-1,2,1,-4], target = 1
输出: 2
解释: 与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

输入: nums = [0,0,0], target = 1
输出: 0

提示

  • 3 <= nums.length <= 1000
  • -1000 <= nums[i] <= 1000
  • -104 <= target <= 104

思路

这题可以借助上一题三数之和的思路,上一题是找到之和为 0 的,这题是找到之和离 target 最接近的

  • 首先将前三项之和当成答案暂存起来
  • 然后对数组进行升序排序,开始遍历第一项到倒数第三项
  • 左指针指向当前项的下一项,右指针指向最后一项
  • 判断当前遍历项和左右指针指向的数字相加与 target 的差值是否小于记录的答案与 target 的差值,是则覆盖答案
  • 判断之和是否等于 target ,是则将答案返回,结束循环
  • 大于 target 则移动右指针,反之移动左指针,需跳过值相同项
  • 当左指针与右指针相遇后,进入下一个循环,如果循环项与上一项相同,跳入下一个循环
  • 最后返回记录的结果即可

代码实现

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var threeSumClosest = function(nums, target) {
    const len = nums.length
    // 升序排序
    nums.sort((a, b) => (a - b))
    // 记录前三项之和
    let res = nums[0] + nums[1] + nums[2]
    for(let i = 0; i < len - 2; i++) {
        // 跳过相同项
        if (i > 0 && nums[i] === nums[i - 1]) continue
        let num = nums[i], // 当前项
            x = i + 1  // 下一项
            y = len - 1  // 最后一项
        while(y > x) {
            // 三数之和
            const sum = num + nums[x] + nums[y]
            // 判断差值  覆盖res
            if (Math.abs(target - sum) < Math.abs(target - res)) {
                res = sum
            }
            // 移动指针
            if(sum > target) {
                do{ y-- } while(nums[y] === nums[y + 1] && y > x)
            } else if(sum < target) {
                do{ x++ } while(nums[x] === nums[x - 1] && y > x)
            } else {
                // 差值为 0 直接返回
                return target
            }
        }
    }
    return res
};