题目链接:16. 最接近的三数之和 - 力扣(LeetCode)
具体思路:先把数组按升序的方式排好,利用数组的前三个数先算出一个与target的差距值Closest。外层循环按顺序先选定第一个数,然后在内循环里面定义left和right下标,通过左右下标遍历剩下的数,每选到begin和end对应的数就和第一个数加到一起求和得到threeSum,比较threeSum与target的差距是否比Closest与target的差距值更小,如果更小就更新Closest为threeSum;更新完之后再检查threeSum,如果threeSum比target大,那证明right对应的数选大了(前面已经排好序),那就right--,left不变;如果threeSum比target小,那证明left对应的数选小了,那就left++,right不变;直到left==right就完成了一次循环;中途如果遇到threeSum==target,那就直接返回了,这是最好的结果。
以下是参考代码,已经配上详细的注释,相信各位小伙伴们都能很轻易地看懂并掌握这道题哦。
时间复杂度:O(N^2),空间复杂度O(1)
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
//先把数组排好序,方便后面的选数
sort(nums.begin(), nums.end());
//先利用数组的前三个元素定一个最接近的三数之和
//切记不能随意赋予一个不属于数组中的值,因为这回影响结果
int Closest = nums[0] + nums[1] + nums[2];
int i = 0;
//外层循环选的是第一个数,所以最多选到倒数第三个数即可
for (i = 0; i < nums.size() - 2; i++)
{
//利用左右下标选第二个和第三个数
int left = i + 1;
int right = nums.size() - 1;
//左下标left不能超过右下标right,等于也不用算上,因为同一个数字
//不能选两次
while (left < right)
{
//计算三数之和
int threeSum = nums[i] + nums[left] + nums[right];
//比较新算出的threeSum与target的差距与原来的最小差距
//如果更小就更新Closest
if (abs(threeSum - target) < abs(Closest - target))
{
Closest = threeSum;
}
//算出的三数之和如果比target小,说明left位置的数选小了,需要
//left++来尽可能地缩小threeSum和target的差距(数组是升序)
if (threeSum < target)
{
left++;
}
//算出的三数之和如果比target大,说明right位置的数选大了,需要
//right--来尽可能地缩小threeSum和target的差距(数组是升序)
else if (threeSum > target)
{
right--;
}
//如果threeSum==target,那这个threeSum就是最接近target的了
//直接返回即可
else
{
return threeSum;
}
}
}
//如果没有出现threeSum==target的情况,那么这个记录的Closest就是
//数组中任意选择三个数相加与target差距值最小的结果了,返回Closest
return Closest;
}
};
以上就是这道题的一个简单的解法,你学会了吗?如果对你有所帮助,那么请点个小心心,顺便点点关注呗,后期还会持续更新力扣的经典题目哦,我们下期见!!!