LeetCode 16

https://leetcode.cn/problems/3sum-closest/description/

难度:中等

高频面试题汇总:https://www.yuweihung.com/posts/2025/lc-hot/

本题比三数之和增加了一个 min_diff 变量维护 |s - target| 最小值。

时间复杂度:\(O(n^2)\),其中 n 为 nums 的长度。排序 O(nlogn)。外层循环枚举第一个数,然后 O(n) 双指针。所以总的时间复杂度为 \(O(n^2)\)。

空间复杂度:O(1)。返回值不计入,忽略排序的栈开销。

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        ranges::sort(nums);
        int ans, n = nums.size();
        int min_diff = INT_MAX;
        for (int i = 0; i < n - 2; i++) {
            int x = nums[i];
            if (i > 0 && x == nums[i - 1]) {
                continue; // 优化三
            }

            // 优化一
            int s = x + nums[i + 1] + nums[i + 2];
            if (s > target) { // 后面无论怎么选,选出的三个数的和不会比 s 还小
                if (s - target < min_diff) {
                    ans = s; // 由于下面直接 break,这里无需更新 min_diff
                }
                break;
            }

            // 优化二
            s = x + nums[n - 2] + nums[n - 1];
            if (s < target) { // x 加上后面任意两个数都不超过 s,所以下面的双指针就不需要跑了
                if (target - s < min_diff) {
                    min_diff = target - s;
                    ans = s;
                }
                continue;
            }

            // 双指针
            int j = i + 1, k = n - 1;
            while (j < k) {
                s = x + nums[j] + nums[k];
                if (s == target) {
                    return target;
                }
                if (s > target) {
                    if (s - target < min_diff) { // s 与 target 更近
                        min_diff = s - target;
                        ans = s;
                    }
                    k--;
                } else { // s < target
                    if (target - s < min_diff) { // s 与 target 更近
                        min_diff = target - s;
                        ans = s;
                    }
                    j++;
                }
            }
        }
        return ans;
    }
};