【前端也得会算法】16. 最接近的三数之和 [ 中等 ]

325 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

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

返回这三个数的和。

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

示例

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

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

二、题解:

方法一 三循环比较法

  • 原理。根据所有记录三数之和,得到最小的值
  • 思路。先记录所有记录三数之和,再循环判断最小的值

代码:

var threeSumClosest = function(nums, target) {
    let arr = []
    for(let i =0 ;i<nums.length;i++){
        for(let j = i+1;j<nums.length;j++){
            for(let k = j+1;k<nums.length;k++){
                console.log(nums[i], nums[j], nums[k])
                arr.push(nums[i]+nums[j]+nums[k])
            }
        }
    }
    let min = Math.abs(target-arr[0])
    let minNum = arr[0]
    for(let i = 1 ;i<arr.length;i++){
        let item = arr[i]
        let diffNum = Math.abs(target-item)
        if(diffNum < min){
            minNum = item
            min = diffNum
        }
    }
    return minNum
};

最后超时了,只能优化下

  • 优化思路。循环的时候就判断最小值即可。

代码:

var threeSumClosest = function(nums, target) {
    let sum = 0
    let min = nums[0]+nums[1]+nums[2]
    for(let i =0 ;i<nums.length-2;i++){
        for(let j = i+1;j<nums.length-1;j++){
            for(let k = j+1;k<nums.length;k++){
                sum = (nums[i] + nums[j] + nums[k]);
                if(Math.abs(target-sum) < Math.abs(target-min)){
                    min = sum
                }
            }
        }
    }
    
    return min
};

image.png

方法二 双指针遍历法

  • 原理。先对输入数组排序,排序后利用双指针取值计算判断。这里判断大小后需要移动指针,继续判断。

代码:

const threeSumClosest = (nums, target) => {
    nums.sort((a, b) => a - b);
    let min = Infinity;
    const len = nums.length;
    for (let i = 0; i < len; i++) {
        let [left, right] = [i + 1, len - 1];
        while (left < right) {
            const sum = nums[i] + nums[left] + nums[right];
            if (Math.abs(sum - target) < Math.abs(min - target)) {
                min = sum;
            }
            if (sum < target) {
                left++;
            } else if (sum > target) {
                right--;
            } else {
                return sum;
            }
        }
    }
    return min;
};

image.png

方案比较

方案一 时间复杂度O(n3) 方案二 时间复杂度O(n2)

三、总结

  • 此题可以三循环比较法双指针遍历法两种方案
  • 三循环比较法主要是根据所有记录三数之和,得到最小的值
  • 双指针遍历法先对输入数组排序,排序后利用双指针取值计算判断。这里判断大小后需要移动指针,继续判断。

文中如有错误,欢迎在评论区指正