Leetcode16.最接近的三数之和(c++,beats 81.94%,附详细解释~)

 本题依旧采用了双指针方法,整体思路和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;
    }
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值