16. 最接近的三数之和|刷题打卡

201 阅读1分钟

一、题目描述

二、解题思路

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 * 找到最小的差值, 拆解成子问题,找到每一种情况的 min(target - (nums[i]+nums[j]+nums[k]))
 * 再拆解,nums[i] + (nums[j]+nums[k])
 * O(n^2)
 * 还是想办法写出所有的情况,穷举出来,硬性可以三重循环,穷举所有情况,但是复杂度太高。
 * 指明双指针, 那么就是需要抓小的现象和逻辑,来进行判断。
 * 在之前的算面积的题中,为什么可以直接使用,双指针,其实跟顺序是有关系的,双指针能够生效的原因也是需要数组是有序的,不然根本不知道如何进行左移和右移。
 */
// var threeSumClosest = function(nums, target) {
//     let min = Infinity;
//     let res;
//     let i = 0;
//     let j = nums.length - 1;
//     while (i < j) {
//         for (let k = i + 1; k < j; k++) {
//             const total = nums[i] + nums[j] + nums[k]
//             if (Math.abs(target - total) < min) {
//                 res = total;
//                 min = Math.abs(target - total);
//                 // 第一次错误,封存,[-1,2,1,-4] 1, 这个解法丢了一种情况,丢失了所有的-1,2,1,覆盖不了所有情况
//             }
//         }
//         i++
//     }

//     return res;
// };

// 当数组是有序的时候,这时候是不是就是可以固定一个数,然后双指针进行左右移动
// 错误:往
// var threeSumClosest = function(nums, target) {
//     let sortNums = nums.sort((a, b) => a - b);
//     let diff = Infinity;
//     let val = null
//     for (let i = 0; i < sortNums.length - 2; i++) {
//         let l = i + 1;
//         let r = sortNums.length-1;
//         while (l < r) {
//             const total = sortNums[i] + sortNums[l] + sortNums[r];
//             if (Math.abs(target - total) < diff) { // 关键点,第一次采用的 Math.abs(),漏掉负数的情况[1,1,-1,-1,3],-1,错误输出成了 1
//                 diff = target - total;
//                 val = total;
//                 l++;
//             } else {
//                 r--;
//             }
//         }
//     }

//     return val;
// }

var threeSumClosest = function(nums, target) {
    nums.sort((a, b) => a - b);
    let res = nums[0] + nums[1] + nums[nums.length - 1];
    for (let i = 0; i < nums.length - 2; i++) {
        let l = i + 1;
        let r = nums.length-1;
        while (l < r) {
            const sum = nums[i] + nums[l] + nums[r];
            // 看了题解,这边把移动指针和值拆分掉,会清晰很多
            if  (sum > target ) {
                r--
            } else {
                l++
            }

            if (Math.abs(target - sum) < Math.abs(target - res)) {
                res = sum
            }
        }
    }

    return res;
}

三、总结

总结:双指针基础是数组需要是有序的,或者是数组的位置是有关系的,才能生效。所以无序需要先排序。自己犯的几个错误:

  1. sort 是对原数组进行排序;
  2. 指针移动的时候最好跟逻辑拆分开来,这样便于我们进行逻辑书写;
  3. 移动指针的逻辑一定要想清楚,最开始写错了这边的逻辑。 if (sum < target ) { r--}