双指针专题

6 阅读2分钟

283.移动零

题目要求在保持非零数顺序情况下,把所有零移到末尾。那么即可用双指针,r指针每次遇到非零数,与l指针进行交换,然后移动l指针,直到r走完。

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int l=0,r=0;
        int n=nums.size();
        while(r<n){
            if(nums[r]){
                swap(nums[l],nums[r]);
                l++;
            }
            r++;
        }
    }
};

11.盛最多水的容器

盛水量的多少由两边高度的较小值与宽度的乘积决定,所以要维护一个ans对指针变化后的值进行更新。然后使用双指针,每次移动的指针肯定是矮的一端,才能保证之后更新的结果可能更大。

class Solution {
public:
    int maxArea(vector<int>& height) {
        int l=0,r=height.size()-1;
        int ans=0;
        while(l<r){
            int area=min(height[l],height[r])*(r-l);
            ans=max(ans,area);
            if(height[l]<height[r]){
                l++;
            }else{
                r--;
            }
        }
        return ans;
    }
};

15.三数之和

排序后,对于每一个nums[i],只需对其后面的数字判断是否存在三者相加为0即可。由于单调性,双指针从两端向中间移动,更新答案。要注意的是每一个nums[i]不能等于nums[i-1],否则会重复计算结果。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n=nums.size();
        sort(nums.begin(),nums.end());
        vector<vector<int>>ans;
        for(int i=0;i<n-2;i++){
            int x=nums[i];
            if(i&&x==nums[i-1])continue;
            if(x+nums[i+1]+nums[i+2]>0){
                break;
            }
            if(x+nums[n-1]+nums[n-2]<0)continue;
            int j=i+1,k=n-1;
            while(j<k){
                int s=x+nums[j]+nums[k];
                if(s>0){
                    k--;
                }else if(s<0){
                    j++;
                }else{
                    ans.push_back({x,nums[j],nums[k]});
                    for(j++;j<k&&nums[j]==nums[j-1];j++);
                    for(k--;j<k&&nums[k]==nums[k+1];k--);
                }
            }

        }
        return ans;
    }
};

42.接雨水

对于所接的雨水,由两端最高高度的较小值决定,可以分为多个小段,每一段的水等于两端较小值减去height[i],哪边最高高度较小先结算哪一边。

class Solution {
public:
    int trap(vector<int>& height) {
        int n=height.size();
        int l=0,r=n-1,ans=0,l_m=0,r_m=0;
        while(l<r){
            l_m=max(l_m,height[l]);
            r_m=max(r_m,height[r]);
            if(l_m<r_m){
                ans+=l_m-height[l++];
            }else{
                ans+=r_m-height[r--];
            }
        }
        return ans;
    }
};