思维导图整理大厂面试高频数组补充1: 最接近的三数之和 和 三数之和 的两个不同之处, 力扣16
此专栏文章是对力扣上算法题目各种方法的总结和归纳, 整理出最重要的思路和知识重点并以思维导图形式呈现, 当然也会加上我对导图的详解.
目的是为了更方便快捷的记忆和回忆算法重点(不用每次都重复看题解), 毕竟算法不是做了一遍就能完全记住的. 所以本文适合已经知道解题思路和方法, 想进一步加强理解和记忆的朋友, 并不适合第一次接触此题的朋友(可以根据题号先去力扣看看官方题解, 然后再看本文内容).
关于本专栏所有题目的目录链接, 刷算法题目的顺序/注意点/技巧, 以及思维导图源文件问题请点击此链接.
想进大厂, 刷算法是必不可少的, 欢迎和博主一起打卡刷力扣算法! 博主同步更新了算法视频讲解, 更易于理解, 不想看文章的 欢迎来看!
关注博主获得题解更新的最新消息!!!
0.导图整理

1.和 三数之和 的相同点
原本在整理 n数之和 系列时是没有整理此题的, 后来在重看 三数之和 时, 发现了这样的评论: 百度一面题目: 找三数和最接近0, 只要将此题中的target设置0即可, 所以又重新补充了此题!
本题是 三数之和 的进阶版, 在思想上和 三数之和 还是很相似的: 先对数组进行排序, 之后用双指针进行空间优化, 同时注意去重操作. 本质的思想几乎是一样的, 所以对本题不太理解的朋友, 可以先看完上面链接中的 三数之和, 再来看本题题解.
但还是有一些和 三数之和 不同的地方, 主要体现在下面的两个方面:
2.判断的情况不同
在 三数之和 中只需要判断相等这一种情况, 其他情况不需要判断, 操作起来是非常简便的, 而本题中每次求和之后都需要进行判断(无论是相等, 还是大于或小于的情况)来找出最接近的数, 这大大增加需要进行判断的工作量, 所以在代码的写法上也有很大的不同之处.
3.去重的方式不同
因为 三数之和 没那么多的判断情况, 所以利用了两层for循环来遍历, 去重的操作也比较简单.
        for first in range(n):
            # 需要和上一次枚举的数不相同
            if first > 0 and nums[first] == nums[first - 1]:
                continue
            ......
            # 枚举 b
            for second in range(first + 1, n):
                # 需要和上一次枚举的数不相同
                if second > first + 1 and nums[second] == nums[second - 1]:
                    continue
 
 而本题中判断情况比较多, 不方便使用两重for循环(我也尝试了使用二重循环, 但发现在去重时候非常复杂, 不适合使用此种方法), 所以采用了while语句来进行双指针的遍历, 这样在去重操作上会简便很多, 并且代码中实现的去重方式比官方的要简单, 而且更方便进行记忆!
            if s > target:
                    # 如果和大于 target,移动 c 对应的指针
                    k -= 1
                    # 移动到下一个不相等的元素
                    while j < k and nums[k] == nums[k+1]:
                        k -= 1
 
 4.最大最小值优化
可以计算出每次三数之和的最大最小值和目标值进行比较, 也可以进行优化, 其实这种方法早在之前讲解的 四数之和 中就已经提到了, 但每次都计算也增加了时间消耗, 在 四数之和 中还是很有优化的必要的, 但是在 三数之和 中是否也适用就要看具体的情况了!
源码
Python:
class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        n = len(nums)
        best = 10**7
        # 枚举 a
        for i in range(n):
            # 保证和上一次枚举的元素不相等
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            # 使用双指针枚举 b 和 c
            j, k = i + 1, n - 1
            while j < k:
                s = nums[i] + nums[j] + nums[k]
                # 如果和为 target 直接返回答案
                if s == target:
                    return target
                # 根据差值的绝对值来更新答案
                if abs(s - target) < abs(best - target):
                    best = s
                if s > target:
                    # 如果和大于 target,移动 c 对应的指针
                    k -= 1
                    # 移动到下一个不相等的元素
                    while j < k and nums[k] == nums[k+1]:
                        k -= 1
                else:
                    # 如果和小于 target,移动 b 对应的指针
                    j += 1
                    # 移动到下一个不相等的元素
                    while j < k and nums[j] == nums[j-1]:
                        j += 1
        return best
 
 java:
class Solution {
    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int n = nums.length;
        int best = 10000000;
        // 枚举 a
        for (int i = 0; i < n; ++i) {
            // 保证和上一次枚举的元素不相等
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            // 使用双指针枚举 b 和 c
            int j = i + 1, k = n - 1;
            while (j < k) {
                int sum = nums[i] + nums[j] + nums[k];
                // 如果和为 target 直接返回答案
                if (sum == target) {
                    return target;
                }
                // 根据差值的绝对值来更新答案
                if (Math.abs(sum - target) < Math.abs(best - target)) {
                    best = sum;
                }
                if (sum > target) {
                    // 如果和大于 target,移动 c 对应的指针
                    --k;
                    // 移动到下一个不相等的元素
                    while (j < k && nums[k] == nums[k+1]) {
                        --k;
                    }
                } else {
                    // 如果和小于 target,移动 b 对应的指针
                    ++j;
                    // 移动到下一个不相等的元素
                    while (j < k && nums[j] == nums[j-1]) {
                        ++j;
                    }
                }
            }
        }
        return best;
    }
}
 
 
- 点赞
 - 收藏
 - 关注作者
 
            
           
评论(0)