Leetcode刷题知——16.最接近的三数之和【排序+三指针】

本文详细介绍了如何使用排序加三指针策略解决LeetCode第16题——找到数组中三个数之和最接近目标值的方法。通过排序数组,然后遍历并用双指针枚举其余两个数,动态更新最接近的三数之和。文中还给出了C++代码实现,并分享了解题心得。
摘要由CSDN通过智能技术生成

Leetcode刷题知——16.最接近的三数之和【排序+三指针】

前言

最近加入了leetcode的刷题计划,每日5题,不过有时候还是交了之前写过的题目。

今天写了这道题目,第16题,16. 最接近的三数之和 - 力扣(LeetCode) (leetcode-cn.com)

感兴趣的小伙伴可以去挑战一下,很简单。

题目

描述

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

示例

输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
输入:nums = [0,0,0], target = 1
输出:0

提示

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

解题思路【排序 + 三指针】

这题我其实一开始是想到排序 + 滑动窗口的思路的,先排序,然后窗口滑动,但是发现了,这样子会错失一些数值,导致WA声一片。

但是如果使用最暴力的三重循环枚举无疑太笨了,我们应该使用复杂度较低的方法实现。

我们其实可以用三指针去解决,先按顺序排序,然后枚举出三数中的最小值,然后在后面的边界去枚举剩下的两个值,对这两个值的枚举,我们可以做一些优化,比如初始化为剩余的最小和最大,然后我们计算三数和,如果小于目标值则移动较小的那一个,如果大于,则移动较大的那一个,然后动态更新答案。

小细节

当枚举出相等时可以直接返回。

Code(C++)

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>

using namespace std;

class Solution
{
public:
    /// <summary>
    /// 排序 + 三指针
    /// 先排序 
    /// 然后使用第一个指针 枚举出三数的最小元素
    /// 然后使用使用两个指针,初始指向后面的左右边界
    /// 根据三数和 与 target的大小关系 进行移动
    /// 如果相等直接返回
    /// </summary>
    /// <param name="nums"></param>
    /// <param name="target"></param>
    /// <returns></returns>
    int threeSumClosest(vector<int>& nums, int target)
    {
        // 排序
        sort(nums.begin(), nums.end());
        int n = nums.size();
        // 三数
        int a, b, c;
        // 初始化一下答案
        int ans = nums[0] + nums[1] + nums[2];
        // 第一个指针
        for (int i = 0; i < n; ++i)
        {
            a = nums[i];
            // 枚举后面两个指针
            for (int j = i + 1, k = n - 1; j < k;)
            {
                b = nums[j], c = nums[k];
                // 相等时直接返回
                if (a + b + c == target)
                {
                    return target;
                }
                // 否则动态更新答案
                int sum = a + b + c;
                ans = (abs(target - sum) < abs(target - ans)) ? sum : ans;
                // 根据数值移动指针
                // 小于目标值,移动b的指针
                if (sum < target)
                {
                    j++;
                }
                // 大于则移动 c的指针
                else
                {
                    k--;
                }
            }
        }
        // 返回答案
        return ans;
    }
};

int main(int argc, char** argv)
{
    int n;
    cin >> n;
    vector<int> nums(n);
    for (int& num : nums)
    {
        cin >> num;
    }
    int target;
    cin >> target;
    Solution sol;
    cout << sol.threeSumClosest(nums, target) << endl;

	return 0;
}

后话

又是充实的一天,真不错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值