题目链接: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; } };