题目描述
Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
Example:
Given array nums = [-1, 2, 1, -4], and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
解题思路及代码示例
暴力破解法(三层循环嵌套)
- 解题思路为:先使用两层循环确定前两个数,再用target减去前两个数的和,其结果为我们希望在第三次循环时可以找到的数,显然,这样算出来的数不一定存在,那么我们的目标就是找到离这个数最近的数,这里“最近的数”使用两数相减的绝对值来衡量,具体做法是使用数组前三个数初始化最近距离,再使用第三层循环遍历数组剩余元素,若新算出的距离小于初始距离,则对最近距离进行更新,直到所有循环结束。
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int min_dist = abs(target - nums[0] - nums[1] - nums[2]);
int result = nums[0] + nums[1] + nums[2];
for (auto it1 = nums.begin(); it1 != nums.end() - 2; ++it1)
{
for (auto it2 = it1 + 1; it2 != nums.end() - 1; ++it2)
{
int tmp = target - *it1 - *it2;
for (auto it3 = it2 + 1; it3 != nums.end(); ++it3)
{
int dist = abs(tmp - *it3);
if (dist < min_dist)
{
min_dist = dist;
result = *it1 + *it2 + *it3;
}
}
}
}
return result;
}
};
Runtime: 304 ms, Memory: 8.6 MB
指针逼近法
- 该算法借鉴了点击这里第三种解法的思想
- 相比暴力破解法,该方法显著降低了求解时间
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());//排序
int min_dist = abs(target - nums[0] - nums[1] - nums[2]);//初始化最近距离
int closest = nums[0] + nums[1] + nums[2];//初始化解
for (auto it1 = nums.begin(); it1 != nums.end() - 2; ++it1)
{
//若nums中头几个元素相同,则头部指针只在第一个元素处停留,下次执行直接跳至非相同元素
if ((it1-nums.begin())>0 && *it1==*(it1-1))
continue;
for (auto it2 = it1+1, it3 = nums.end()-1; it2 < it3;)
{
int sum = *it1 + *it2 + *it3;//候选解
//若候选解距target的距离小于最近距离,则更新最近距离
if (abs(sum-target) < min_dist)
{
min_dist = abs(sum-target);
closest = sum;
if (min_dist == 0)
return closest;
}
//目标是使候选解sum与target尽可能接近,因此在头指针确定的情况下,依据sum与target的插值移动
// 中部指针或者尾指针,始终保持sum接近target,这也是该算法最重要的思想
if (sum-target < 0)
++it2;
else --it3;
}
}
return closest;
}
};
Runtime: 4ms, Memory: 8.7MB