双指针题目


四数之和

在这里插入图片描述

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        vector<vector<int>>ans;
        int n=nums.size();
        for(int i=0;i<n;++i){
            for(int j=i+1;j<n;++j){
                //双指针
                int left=j+1;
                int right=n-1;
                unordered_set<string>set;
                while(left<right){
                    long long sum=0;
                    sum+=(long long)nums[i]+nums[j]+nums[left]+nums[right];
                    if(sum==target){
                        string s=to_string(nums[i])+" "+to_string(nums[j])+" "+to_string(nums[left])+" "+to_string(nums[right]);
                        if(set.find(s)==set.end()){
                            ans.push_back({nums[i],nums[j],nums[left],nums[right]});
                            set.insert(s);
                        }
                        ++left;
                    }else if(sum>target){
                        --right;
                    }else{
                        ++left;
                    }
                }
                while(j+1<n&&nums[j+1]==nums[j]){
                    ++j;
                }
            }
            while(i+1<n&&nums[i+1]==nums[i]){
                ++i;
            }
        }
        return ans;
    }
};

在这里插入图片描述


最接近的三数之和

在这里插入图片描述

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        int n=nums.size();
        int res=INT_MAX;
        for(int i=0;i<n;++i){
            int left=i+1;
            int right=n-1;
            while(left<right){
                if(nums[i]+nums[left]+nums[right]==target){
                    return target;
                }
                // cout<<left<<" "<<right<<endl;
                res=abs((long long)res-target)<abs(nums[i]+nums[left]+nums[right]-target)?res:nums[i]+nums[left]+nums[right];
                if(nums[i]+nums[left]+nums[right]<target){
                    ++left;
                }else{;
                    --right;
                }
            }
        }
        return res;
    }
};

在这里插入图片描述


盛最多水的容器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述


长度最小的子数组

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int left=0,right=0;
        long long sum=nums[0];
        int n=nums.size();
        int ans=INT_MAX;
        while(left<n&&right<n){
            if(sum>=target){
                ans=ans<right-left+1?ans:right-left+1;
                sum-=nums[left];
                left++;
            }else{
                if(right+1<n){
                    right++;
                    sum+=nums[right];
                }else{
                    right++;
                }
            }
           
        }
        if(sum>=target){
            ans=ans<min(right,n-1)-left+1?ans:min(right,n-1)-left+1;
        }
        
        return ans==INT_MAX?0:ans;
    }
};

在这里插入图片描述


最大连续1的个数 III

在这里插入图片描述

解题思路:

维护 [ l e f t , r i g h t ] [left,right] [left,right] 区间内的 0 0 0 的个数,当前 n u m s [ i ] nums[i] nums[i] 1 1 1 r i g h t right right 指针继续右移;
n u m s [ i ] = 0 nums[i]=0 nums[i]=0 c n t 0 < k cnt0<k cnt0<k r i g h t right right 可以继续右移
一旦 n u m s [ i ] = 0 nums[i]=0 nums[i]=0 c n t 0 = = k cnt0==k cnt0==k 时, l e f t left left 右移, r i g h t right right 不能再右移了

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int left=-1,right=-1;
        int n=nums.size();
        int cnt0=0;
        int ans=0;
        while(left<n&&right<n){
            if(right+1<n&&nums[right+1]==1){
                right++;
            }else{
                if(cnt0<k){
                    right++;
                    if(right<n&&nums[right]==0){
                        cnt0++;
                    }
                }else{
                    if(left>=0&&nums[left]==0){
                        cnt0--;
                    }
                   
                    left++;
                }
            }
            ans=ans>min(right,n-1)-max(0,left)+1?ans:min(right,n-1)-max(0,left)+1;
            
        }

        return ans;
    }
};

在这里插入图片描述


无重复字符的最长子串

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n=s.length();
        if(n==0)return 0;
        int res=1;
        unordered_set<char>set;
        int i=0,j=0;
        while(i<n&&j<n){
            if(set.find(s[j])==set.end()){
                set.insert(s[j]);
                ++j;
            }else{
                res=res>j-i?res:j-i;
                set.erase(s[i]);
                ++i;
            }
        }
        res=res>j-i?res:j-i;
        return res;
    }
};

在这里插入图片描述


构造矩形

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    vector<int> constructRectangle(int area) {
        int left=std::sqrt(area);
        int right=std::sqrt(area);
        vector<int>ans;
        while(left<=right){
            if(left*right==area){
                ans.push_back(right);
                ans.push_back(left);
                return ans;
            }else if(left*right<area){
                right++;
            }else{
                left--;
            }
        }
        return ans;
    }
};

在这里插入图片描述


和为s的连续正数序列

在这里插入图片描述

解题思路:
如果 s u m < t a r g e t sum<target sum<target 则说明指针 r r r 还可以向右拓展使得 s u m sum sum 增大,此时指针 r r r 向右移动,即 r + = 1 r+=1 r+=1
如果 s u m > t a r g e t sum>target sum>target 则说明以 ll 为起点不存在一个 r r r 使得 s u m = t a r g e t sum=target sum=target ,此时要枚举下一个起点,指针 l l l 向右移动,即 l + = 1 l+=1 l+=1
如果 s u m = = t a r g e t sum==target sum==target 则说明我们找到了以 ll 为起点得合法解 [ l , r ] [l,r] [l,r] ,我们需要将 [ l , r ] [l,r] [l,r] 的序列放进答案数组,且我们知道以 ll 为起点的合法解最多只有一个,所以需要枚举下一个起点,指针 ll 向右移动,即 l + = 1 l+=1 l+=1
终止条件即为 l > = r l>=r l>=r 的时候 。

class Solution {
public:
    vector<vector<int>> findContinuousSequence(int target) {
        int left=1;
        int right=2;
        int sum=0;
        vector<vector<int>>ans;
        while(left<right){
            sum=(left+right)*(right-left+1)/2;
            if(sum==target){
                vector<int>v;
                for(int i=left;i<=right;++i){
                    v.push_back(i);
                }
                ans.push_back(v);
                left++;
                sum-=left;
            }else if(sum<target){
                right++;
                sum+=right;
            }else{
                left++;
                sum-=left;
            }
        }
        std::sort(ans.begin(),ans.end(),[&](vector<int>v1,vector<int>v2){
            return v1[0]<v2[0];
        });
        return ans;
    }
};

在这里插入图片描述


两栋颜色不同且距离最远的房子


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
    //双指针
    public int maxDistance(int[] colors) {
        int right=colors.length-1;
        int left=0;
        for(;right>=0;--right){
            if(colors[right]!=colors[0]){
                break;
            }
        }
        for(;left<colors.length;++left){
            if(colors[left]!=colors[colors.length-1]){
                break;
            }
        }
        return Math.max(right-0,colors.length-1-left);
    }
}

在这里插入图片描述



判断子序列

在这里插入图片描述
在这里插入图片描述

class Solution {

    public boolean process(String s,String t){
        if(s.length()>t.length()||t==null)return false;
        int i=0;
        int j=0;
        while(i<s.length()&&j<t.length()){
            if(s.charAt(i)==t.charAt(j)){
                i++;j++;
            }else{
                j++;
            }
        }
        if(i==s.length()){
            return true;
        }
        return false;
    }
    public boolean isSubsequence(String s, String t) {
        return process(s,t);
    }
}

在这里插入图片描述



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值