【算法】16. 最接近的三数之和(多语言实现)

简介: 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在恰好一个解。

16. 最接近的三数之和:

给你一个长度为 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

提示:

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

原题传送门:

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


分析

  • 面对这道算法题目,二当家的陷入了沉思。
  • 这道题和【15. 三数之和】很像,但是不再是找一个值,而是要把可能的值都找一遍,最后确定最接近的值,所以不再是直接跳过大于目标,或者小于目标的值。
  • 由于有三个变量,直观的做法还是暴力三层循环,但还是传说会超时。
  • 同样我们先排个序,可以外层循环遍历作为第一个数。
  • 这里用到双指针的思想,如果是找最接近的两数之和,我们可以将两个指针先定位在有序数组的两端,去判断两数之和是否和目标相等,如果相等就是想要的结果;如果大于目标,我们向左移动右面的指针;如果小于目标,我们就向右移动左边的指针。(如果右面的指针一直向左移动就会让两数之和最小,反之如果让左面的指针一直向右移动就会使两数之和最大,这样两个指针的移动方向虽然固定了,但是却不会漏掉某种组合)
  • 扩展到三数之和,由于外层循环已经确定了第一个数的值,内层其实就是最接近的两数之和。

题解

rust

impl Solution {
   
    pub fn three_sum_closest(mut nums: Vec<i32>, target: i32) -> i32 {
   
        let n = nums.len();
        nums.sort();
        let mut ans = 23001;
        for f in 0..n {
   
            if f == 0 || nums[f] != nums[f - 1] {
   
                let mut s = f + 1;
                let mut t = n - 1;
                while s < t {
   
                    let sum = nums[f] + nums[s] + nums[t];
                    if sum == target {
   
                        return target;
                    }
                    if (sum - target).abs() < (ans - target).abs() {
   
                        ans = sum;
                    }
                    if sum > target {
   
                        let mut t0 = t - 1;
                        while s < t0 && nums[t0] == nums[t] {
   
                            t0 -= 1;
                        }
                        t = t0;
                    } else {
   
                        let mut s0 = s + 1;
                        while s0 < t && nums[s0] == nums[s] {
   
                            s0 += 1;
                        }
                        s = s0;
                    }
                }
            }
        }
        return ans;
    }
}

go

func threeSumClosest(nums []int, target int) int {
   
    n := len(nums)
    sort.Ints(nums)
    ans := 23001

    abs := func(num int) int {
   
        if num < 0 {
   
            return -num
        }
        return num
    }

    for f := 0; f < n; f++ {
   
        if f > 0 && nums[f] == nums[f-1] {
   
            continue
        }
        s, t := f+1, n-1
        for s < t {
   
            sum := nums[f] + nums[s] + nums[t]
            if sum == target {
   
                return target
            }
            if abs(sum-target) < abs(ans-target) {
   
                ans = sum
            }
            if sum > target {
   
                t0 := t - 1
                for s < t0 && nums[t0] == nums[t] {
   
                    t0 -= 1
                }
                t = t0
            } else {
   
                s0 := s + 1
                for s0 < t && nums[s0] == nums[s] {
   
                    s0 += 1
                }
                s = s0
            }
        }
    }

    return ans
}

c++

class Solution {
   
public:
    int threeSumClosest(vector<int>& nums, int target) {
   
        int n = nums.size();
        sort(nums.begin(), nums.end());
        int ans = 23001;
        for (int f = 0; f < n; ++f) {
   
            if (f > 0 && nums[f] == nums[f - 1]) {
   
                continue;
            }
            int s = f + 1;
            int t = n - 1;
            while (s < t) {
   
                int sum = nums[f] + nums[s] + nums[t];
                if (sum == target) {
   
                    return target;
                }
                if (abs(sum - target) < abs(ans - target)) {
   
                    ans = sum;
                }
                if (sum > target) {
   
                    int t0 = t - 1;
                    while (s < t0 && nums[t0] == nums[t]) {
   
                        t0 -= 1;
                    }
                    t = t0;
                } else {
   
                    int s0 = s + 1;
                    while (s0 < t && nums[s0] == nums[s]) {
   
                        s0 += 1;
                    }
                    s = s0;
                }
            }
        }
        return ans;
    }
};

java

class Solution {
   
    public int threeSumClosest(int[] nums, int target) {
   
        int n = nums.length;
        Arrays.sort(nums);
        int ans = 23001;
        for (int f = 0; f < n; ++f) {
   
            if (f > 0 && nums[f] == nums[f - 1]) {
   
                continue;
            }
            int s = f + 1;
            int t = n - 1;
            while (s < t) {
   
                int sum = nums[f] + nums[s] + nums[t];
                if (sum == target) {
   
                    return target;
                }
                if (Math.abs(sum - target) < Math.abs(ans - target)) {
   
                    ans = sum;
                }
                if (sum > target) {
   
                    int t0 = t - 1;
                    while (s < t0 && nums[t0] == nums[t]) {
   
                        t0 -= 1;
                    }
                    t = t0;
                } else {
   
                    int s0 = s + 1;
                    while (s0 < t && nums[s0] == nums[s]) {
   
                        s0 += 1;
                    }
                    s = s0;
                }
            }
        }
        return ans;
    }
}

typescript

function threeSumClosest(nums: number[], target: number): number {
   
    const n = nums.length;
    nums.sort((a, b) => a - b);
    let ans = 23001;
    for (let f = 0; f < nums.length; ++f) {
   
        if (f > 0 && nums[f] === nums[f - 1]) {
   
            continue;
        }
        let s = f + 1;
        let t = n - 1;
        while (s < t) {
   
            const sum = nums[f] + nums[s] + nums[t];
            if (sum === target) {
   
                return target;
            }
            if (Math.abs(sum - target) < Math.abs(ans - target)) {
   
                ans = sum;
            }
            if (sum > target) {
   
                let t0 = t - 1;
                while (s < t0 && nums[t0] === nums[t]) {
   
                    t0 -= 1;
                }
                t = t0;
            } else {
   
                let s0 = s + 1;
                while (s0 < t && nums[s0] === nums[s]) {
   
                    s0 += 1;
                }
                s = s0;
            }
        }
    }
    return ans;
};

python

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        n = len(nums)
        nums.sort()
        ans = 23001
        for f in range(n):
            if f > 0 and nums[f] == nums[f - 1]:
                continue
            s = f + 1
            t = n - 1
            while s < t:
                sum = nums[f] + nums[s] + nums[t]
                if sum == target:
                    return target
                if abs(sum - target) < abs(ans - target):
                    ans = sum
                if sum > target:
                    t0 = t - 1
                    while s < t0 and nums[t0] == nums[t]:
                        t0 -= 1
                    t = t0
                else:
                    s0 = s + 1
                    while s0 < t and nums[s0] == nums[s]:
                        s0 += 1
                    s = s0
        return ans

非常感谢你阅读本文~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://developer.aliyun.com/profile/sqd6avc7qgj7y 博客原创~


相关文章
|
2月前
|
自然语言处理 Rust 算法
【算法】13. 罗马数字转整数(多语言实现)
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 | 字符 | 数值 | |--|--| | I | 1 | | V | 5 | | X | 10 | | L | 50 | | C | 100 | | D | 500 | | M | 1000 | 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1
【算法】13. 罗马数字转整数(多语言实现)
|
2月前
|
设计模式 算法 Java
【数据结构和算法】确定两个字符串是否接近
这是力扣的1657题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。复杂度分析:时间复杂度:O(max⁡{n1,n2}+Clog⁡C),其中 n1 和 n2 分别是字符串 word1 和 word2 的长度,C=26 是字符集大小。空间复杂度:O(C)。
52 1
|
9月前
|
自然语言处理 Rust 算法
【算法】9. 回文数(多语言实现)
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
|
4天前
|
自然语言处理 Rust 算法
【算法】17. 电话号码的字母组合(多语言实现)
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
【算法】17. 电话号码的字母组合(多语言实现)
|
2月前
|
自然语言处理 Rust 算法
【算法】15. 三数之和(多语言实现)
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请 你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复的三元组。
|
2月前
|
自然语言处理 Rust 算法
【算法】14. 最长公共前缀(多语言实现)
编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 ""。
|
2月前
|
自然语言处理 Rust 算法
【算法】11. 盛最多水的容器(多语言实现)
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明: 你不能倾斜容器。
【算法】11. 盛最多水的容器(多语言实现)
|
2月前
|
自然语言处理 Rust 算法
【算法】12. 整数转罗马数字(多语言实现)
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而
|
2月前
|
算法 Java 流计算
Java【算法分享 02】道格拉斯-普克 Douglas-Peucker 抽稀算法分析及15w个坐标点抽稀到3.7w耗时从360s+优化到365ms接近1000倍的速度提升(并行流+多线程+泛型)
Java【算法分享 02】道格拉斯-普克 Douglas-Peucker 抽稀算法分析及15w个坐标点抽稀到3.7w耗时从360s+优化到365ms接近1000倍的速度提升(并行流+多线程+泛型)
133 0
|
8月前
|
自然语言处理 Rust 算法
【算法】10. 正则表达式匹配(多语言实现)
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符 * 匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。