最接近的三数之和--力扣

Posted 穿迷彩服的鲨鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最接近的三数之和--力扣相关的知识,希望对你有一定的参考价值。


前言

提示:给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。


一、示例

示例:

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

提示:

3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^4

二、代码解析

1.暴力解法

代码如下(示例):

int threeSumClosest(vector<int>& nums, int target)
{
	int n = nums.size();
	int tempMin = 100000000;
	int close = 0;
	for (int i = 0; i < n; ++i)
	{
		for (int j = i + 1; j < n; ++j)
		{
			for (int k = j + 1; k < n; ++k)
			{
				int temp = abs(nums[i] + nums[j] + nums[k] - target);
				if (tempMin> temp)
				{
					tempMin = temp;
					close = nums[i] + nums[j] + nums[k];
				}
			}
		}
	}
	return close;
}

结果

在这里插入图片描述

2.排序+双指针

代码如下(示例):

/// <summary>
/// 排序+双指针
/// </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 best = 1e7;

	// 根据差值的绝对值来更新答案
	auto update = [&](int cur)
	{
		if (abs(cur - target) < abs(best - target))
		{
			best = cur;
		}
	};

	// 枚举 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;
			}
			update(sum);
			if (sum > target) 
			{
				// 如果和大于 target,移动 c 对应的指针
				int k0 = k - 1;
				// 移动到下一个不相等的元素
				while (j < k0 && nums[k0] == nums[k]) 
				{
					--k0;
				}
				k = k0;
			}
			else
			{
				// 如果和小于 target,移动 b 对应的指针
				int j0 = j + 1;
				// 移动到下一个不相等的元素
				while (j0 < k && nums[j0] == nums[j]) 
				{
					++j0;
				}
				j = j0;
			}
		}
	}
	return best;
}

结果

在这里插入图片描述

3.测试

代码如下(示例):

#include<vector>
#include<algorithm>
#include <iostream>
using namespace std;

/// <summary>
/// 排序+双指针
/// </summary>
/// <param name="nums"></param>
/// <param name="target"></param>
/// <returns></returns>
int threeSumClosest(vector<int>& nums, int target)
{
	/*int n = nums.size();
	int tempMin = 100000000;
	int close = 0;
	for (int i = 0; i < n; ++i)
	{
		for (int j = i + 1; j < n; ++j)
		{
			for (int k = j + 1; k < n; ++k)
			{
				int temp = abs(nums[i] + nums[j] + nums[k] - target);
				if (tempMin> temp)
				{
					tempMin = temp;
					close = nums[i] + nums[j] + nums[k];
				}
			}
		}
	}
	return close;*/
	sort(nums.begin(), nums.end());
	int n = nums.size();
	int best = 1e7;

	// 根据差值的绝对值来更新答案
	auto update = [&](int cur)
	{
		if (abs(cur - target) < abs(best - target))
		{
			best = cur;
		}
	};

	// 枚举 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;
			}
			update(sum);
			if (sum > target) 
			{
				// 如果和大于 target,移动 c 对应的指针
				int k0 = k - 1;
				// 移动到下一个不相等的元素
				while (j < k0 && nums[k0] == nums[k]) 
				{
					--k0;
				}
				k = k0;
			}
			else
			{
				// 如果和小于 target,移动 b 对应的指针
				int j0 = j + 1;
				// 移动到下一个不相等的元素
				while (j0 < k && nums[j0] == nums[j]) 
				{
					++j0;
				}
				j = j0;
			}
		}
	}
	return best;
}

int main()
{
	vector<int> nums = { -1,2,1,-4 };
	int target = 1;
	cout << threeSumClosest(nums, target);
	return 0;
}

结果

在这里插入图片描述


总结

在这里插入图片描述

以上是关于最接近的三数之和--力扣的主要内容,如果未能解决你的问题,请参考以下文章

力扣16. 最接近的三数之和

力扣专题——“16. 最接近的三数之和”

力扣——3sum closest(最接近的三数之和)python 实现

思维导图整理大厂面试高频数组补充1: 最接近的三数之和 和 三数之和 的两个不同之处, 力扣16

思维导图整理大厂面试高频数组补充1: 最接近的三数之和 和 三数之和 的两个不同之处, 力扣16

思维导图整理大厂面试高频数组补充1: 最接近的三数之和 和 三数之和 的两个不同之处, 力扣16