本题依旧采用了双指针方法,整体思路和15题解题思路差不多
整体思路:
(1)先检查是否nums元素个数为3,若果为3,直接返回此3个元素之和。如果个数超过3,将nums从小到大排序,方便之后定指针移动顺序。
(2)定义int型的min变量并为其赋初值,含义为最接近目标的元素之和。
(3)从now=0至now<nums.size()开始循环,每次先选定循环数,再定义left、right左右指针,左指针赋初值为now+1,右指针赋初值为nums.size()-1。
(4)开始left、right指针的移动,循环条件为while(left<right)。在循环内记录下当下选定的三个元素数字之和now_sum,若正好与target值相同,则返回now_sum,若不同则判断当前数值大于目标还是小于目标,若大于目标则移动右指针使其所指数值变小,若小于则移动左指针使其数值变大。
(5)每次指针移动时,都记录当下选定的三个数值之和即now_sum,将其与min比较,只有当min>now_sum时,才将now_sum数值赋予min,再集训循环比较。
(6)移动指针时为了优化,若移动前后指针数值相同,则继续移动,直至数值不同。若已经到了(left+1==right)情况下,将min与now_sum进行比较赋值后直接退出。
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());//先将其进行从小到大的排序
if(nums.size()==3) return nums[0]+nums[1]+nums[2];
int min=nums[0]+nums[1]+nums[nums.size()-1];
for(int now=0;now<nums.size()-2;now++){
int left=now+1;int right=nums.size()-1;//定义左右指针开始位置
int last_sum,now_sum;//定义上一次循环及本次循环的三个数的和
//last_sum=nums[now]+nums[left]+nums[right];//赋初值
while(left<right){
now_sum=nums[now]+nums[left]+nums[right];
//min=now_sum;
if(now_sum-target==0){
//如果恰好当前的和与目标值相等,则直接返回目标
min=now_sum;
return min;
}
else {
if(left+1==right) {//已经到了最后一次还未找到转折点
min=(abs(min-target)>abs(now_sum-target))?now_sum:min;
break;
}
//还未到本轮的最后一次,如果现在的和数值过大则移动右指针,过小移动左指针
if(now_sum-target>0){
min=(abs(min-target)>abs(now_sum-target))?now_sum:min;
right--;
//如果移动后数值一样,则继续移动
while(nums[right+1]==nums[right]) {
right--;
if(right<0) break;
}
}
else if(now_sum-target<0){
min=(abs(min-target)>abs(now_sum-target))?now_sum:min;
left++;
//如果移动后数值一样,则继续移动
while(nums[left-1]==nums[left]){
left++;
if(left>=nums.size()) break;
}
}
}
}
}
return min;
}
};