《leetcode》第一阶段汇总(10-20题)(二)

15. 3Sum 

  在2Sum问题中,可以使用one pass结合哈希表快速得到问题的答案。但是如果想在3Sum问题中,沿用之前的方式必然要解决重复元素的问题。现在有种可以解决Nsum的思路,基于2Sum的双指针方法。

class Solution {
public:
      vector<vector<int>> threeSum(vector<int>& nums){
        vector<vector<int>> ans;
        int tmp;
        sort(nums.begin(),nums.end());
        for(int i=0;i<nums.size();++i){
            //此时不会漏掉任何元素,且避免重复。如果有重复元素构成答案的话,在第一次判断该元素的时候就会得到答案
            while( i!=0 && nums[i-1]==nums[i]) ++i;
            int j=i+1,k=nums.size()-1;
            for(;j<k;){ 
                tmp=nums[l]+nums[i]+nums[j]+nums[k];
                if(tmp == 0){
                    ans.push_back({nums[i],nums[j],nums[k]});
                    ++j;
                    //这里因为i是唯一的,j如果此时有重复一定会有重复答案,所以j直接跳过重复元素,同样的如果判断该元素的
                    //时候答案包括自身,则在第一次的时候,就已经考虑了。
                    while (j < k && nums[j] == nums[j-1]) ++j;
                }
                else if(tmp >0)
                    --k;
                else
                    ++j;
            }
        }
        return ans;
    }
};

18. 4Sum 

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> ans;
        int tmp;
        sort(nums.begin(),nums.end());
        //多了一个for循环
        for(int l=0;l<nums.size();++l){
            while( l!=0 && nums[l-1]==nums[l]) ++l;
            for(int i=l+1;i<nums.size();++i){
                while( i!=l+1 && nums[i-1]==nums[i]) ++i;
                int j=i+1,k=nums.size()-1;
                for(;j<k;){ 
                    tmp=nums[l]+nums[i]+nums[j]+nums[k]-target;
                    if(tmp == 0 ){
                        ans.push_back({nums[l],nums[i],nums[j],nums[k]});
                        ++j;
                    while (j < k && nums[j] == nums[j-1]) ++j;
                }
                else if(tmp >0)
                    --k;
                else
                    ++j;
            }
        }
      }
      return ans;
    }
};

16. 3Sum Closest

  倘若题目要求变成最接近target的三个数之和(或者三个数,此时多增加些变量而已),那么只需要在3Sum的解决方案中,用变量跟踪最三数之和最接近target的时候。该算法本质上也是一种遍历算法,复杂度为 O ( n 2 )

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        int ans1=0xfffff,tmp,ans2;
        sort(nums.begin(),nums.end());
        for(int i=0;i<nums.size();i++){
            while( i!=0 && nums[i-1]==nums[i]) i++;
            for(int j=i+1,k=nums.size()-1;j<k;){ 
                tmp=nums[i]+nums[j]+nums[k]-target;
                if(tmp == 0 )
                    return target;
                //注意abs函数在最小负数的情况下,还是返回该最小负数。
                if(ans1>abs(tmp)){
                    ans1=abs(tmp);
                    ans2=tmp+target;
                }
                if(tmp >0)
                    k--;
                else
                    j++;
            }
        }
        return ans2;
    }
};

小结

  10-20题总结完毕,并非完整的记录了每一个题,而是选取了一些比较好的题。本文总结了SUM系列问题的求法,该方法为双指针法,能够将时间复杂度降次。特别的,11题Container With Most Water也采用了双指针方法。可以发现,双指针法需要问题性质的满足情况来决定递增哪一个指针,每次只递增一个指针达到优化时间复杂度的效果。

猜你喜欢

转载自blog.csdn.net/lovestackover/article/details/80950267