Leetcode15——三数之和(问题降维,对撞指针,剪枝)

对撞指针

两个指针,分别指向数组(一般是排序后的数组)的头尾,根据不同的条件依次向中间靠拢
可以用来解决:找数组中满足一定条件了两个数(不重复)的问题

class Solution {
public:
    vector> threeSum(vector& nums) {
        vector >res;  //结果
        sort(nums.begin(),nums.end());  //排序
        if(nums.empty() || nums.front()>0 || nums.back()<0)   //如果nums为空,或全正,全负,则返回空
            return {};
        
        for(int i=0;i0)   break;               //剪枝1:升序排序后,最小值若大于0,则必定不满足条件,且之后的值也都不满足,直接break跳出大循环
            if(i>0 && fix==nums[i-1])    continue;    //防fix重复:如果nums[i]=num[i-1],则跳出当前循环,因为没必要对相同的值求解;i>0的条件是防止下标下溢,即i-1=-1
            //对撞指针
            int l=i+1,r=nums.size()-1;       //指针l和指针r分别从正向和反向遍历i后边的值(称为对撞指针?)
            while(l{nums[i],nums[l],nums[r]});   //将三个数组成数组push到res中
                        l++;r--;                                                  //l向前走,r向后走
                    } 
                    else if(nums[l]==nums[l-1])   //防l重复
                        l++;
                    else if(nums[r]==nums[r+1])   //防r重复
                        r--;
                    else{
                        res.push_back(vector{nums[i],nums[l],nums[r]});  //是不是和if可以合并??因为{}中的操作完全一致
						//不可以,因为进行防重复操作,会导致r的溢出或者l去和fix比较(实际也是l的处理范围溢出)
                        l++;r--;
                    }
                    
                }
                else if(nums[l]+nums[r]<-fix)    //如果小于-fix,即三数之和<0,要增加小的那个数
                    l++;
                else                           //如果三数之和大于0,要降低大的那个数
                    r--;
            }
        }
        return res;
    }
}

作者:crunch
链接:https://leetcode-cn.com/problems/two-sum/solution/3sum-using-c-by-crunch/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(算法练习,C++学习)