Loading

2023.7.10 最接近的三数之和

image

排序+二分

可以先对数组排序,这样就拥有了单调性,就可以在其上做二分。
首先枚举第一个数a,然后枚举第二个数b,此时与target的差值就是diff = abs(target - a - b)。由于题目要求找最接近的,所以候选元素c有两种可能,一种是c <= diff,一种是c > diff。正好对应二分的两种情况,所以二分查找一下就行,时间复杂度是\(O(n^2logn)\)

排序+双指针

可以用二分的题,通常都可以优化一下使用双指针。同样也是先排序,获得单调性。
枚举第一个数a,其下标为i,此时可以令b为i+1,c为n-1。此时的和sum = a + b + c,如果该和sum > target,那么令指向c的指针往前移动,如果sum < target,令指向b的指针往后移动,如果sum = target,直接返回答案。
对于每一个a都进行一次这样的双指针检验,所以是时间复杂度是\(O(n^2)\)

impl Solution {
    pub fn three_sum_closest(nums: Vec<i32>, target: i32) -> i32 {
        let n = nums.len();
        let mut nums = nums;
        nums.sort();

        let mut res = 0x3f3f3f3f;
        let mut update = |cur: i32| {
            if (cur - target).abs() < (res - target).abs() { res = cur; }
        };

        for i in 0..n-2 {
            if i > 0 && nums[i] == nums[i - 1] { continue; }
            let (mut j, mut k) = (i + 1, n - 1);
            while j < k {
                let sum = nums[i] + nums[j] + nums[k];
                if sum == target { return target; }
                update(sum);

                if sum > target {
                    let mut dk = k - 1;
                    while j < dk && nums[dk] == nums[k] { dk -= 1; }
                    k = dk;
                }
                else {
                    let mut dj = j + 1;
                    while dj < k && nums[dj] == nums[j] { dj += 1; }
                    j = dj;
                }
            }
        }
        res
    }
}
posted @ 2023-07-10 10:25  烤肉kr  阅读(32)  评论(0编辑  收藏  举报