力扣题目解析--最接近的三数之和

题目

给你一个长度为 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
解释:与 target 最接近的和是 0(0 + 0 + 0 = 0)。

提示:

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

代码展示 

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        int n = nums.size();
        int closestSum = nums[0] + nums[1] + nums[2]; // 初始化最接近的和

        for (int i = 0; i < n - 2; i++) {
            int left=i+1;//Left的值是从零开始数组第一个值的下一个值。
            int right=n-1;//right是数组的最后一个值
            //这样做的目的是,每一次循环,数组中的每一个值都会在整个数组内寻找能和他相匹配达成目标值的另外两个数。
            //接下来的while循环目的就是为了以目前for循环当前数组的值,在数组的范围内寻找能和他达成目标值的另外两个数。
            //因此left和right的值才会设成这个样子
            //这就是双指针循环的必备因素,也是双指针循环的基本逻辑。

            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                if (sum == target) {
                    return sum; // 如果找到完全匹配的目标值,直接返回
                }

                if (abs(target - sum) < abs(target - closestSum)) {
                    closestSum = sum; // 更新最接近的和
                }

                if (sum < target) {
                    left++;
                } else {
                    right--;
                }
            }
        }

        return closestSum;
    }
};

写者心得 

题目类似于昨天的三数之和,写者在认真总结和反思了昨天所学的三数之和后,当看到今天的题目认为应该采取同样的双指针循环来寻找最接近的三数之和。今天的思路整体完全没有任何问题,唯独有一点,在我考虑的应该通过绝对值。来判断是否接近的时候,我并不会使用绝对值的函数abs。因此写了一个私有函数,纠错之后发现没有必要,于是删了。产生了一定的混乱,不过没关系,对于这道题目的整个思路,整个逻辑没有任何影响,只是因为学习上的不足。

详细解析

  1. 排序数组

    sort(nums.begin(), nums.end());
    • 这行代码对输入的数组 nums 进行排序,排序后数组按升序排列。排序的目的是为了后续使用双指针法时能够高效地查找最接近目标值的三个数。
  2. 获取数组长度

    int n = nums.size();
    • 这行代码获取数组的长度,并将其存储在变量 n 中。
  3. 初始化最接近目标值的和

    int closestSum = nums[0] + nums[1] + nums[2];
    • 这行代码初始化 closestSum 为数组前三个数的和。这是为了确保 closestSum 有一个初始值,以便后续比较。
  4. 遍历数组

    for (int i = 0; i < n - 2; i++) {
    • 这行代码开始一个 for 循环,遍历数组。循环变量 i 从 0 到 n - 2,这是因为我们需要选择三个数,所以 i 最多只能到 n - 2
  5. 初始化左右指针

    int left = i + 1;
    int right = n - 1;
    • 这两行代码初始化左指针 left 和右指针 right。左指针从当前数的下一个位置开始,右指针从数组的最后一个位置开始。
  6. 双指针法

    while (left < right) {
    • 这行代码开始一个 while 循环,条件是左指针 left 小于右指针 right。这个循环的目的是在当前选定的第一个数 nums[i] 的基础上,通过移动左右指针找到最接近目标值的三个数。
  7. 计算当前和

    int sum = nums[i] + nums[left] + nums[right];
    • 这行代码计算当前三个数的和,并将其存储在变量 sum 中。
  8. 检查是否等于目标值

    if (sum == target) {
        return sum;
    }
    • 这行代码检查当前和是否等于目标值。如果等于,直接返回该和,因为这是最接近目标值的情况。
  9. 更新最接近的和

    if (abs(target - sum) < abs(target - closestSum)) {
        closestSum = sum;
    }
    • 这行代码检查当前和 sum 是否比当前最接近的和 closestSum 更接近目标值。如果是,则更新 closestSum
  10. 调整指针位

    if (sum < target) {
        left++;
    } else {
        right--;
    }
    • 这两行代码根据当前和 sum 与目标值 target 的关系调整指针位置:
      • 如果 sum 小于 target,则移动左指针 left 向右,尝试增加和。
      • 如果 sum 大于 target,则移动右指针 right 向左,尝试减少和。
  11. 返回最接近目标值的和

    return closestSum;
    • 这行代码在所有可能的组合中找到最接近目标值的和,并返回该和。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值