牛客101:双指针

目录

一、合并两个有序的数组

二、判断是否为回文字符串

三、合并区间

四、最小覆盖子串

五、反转字符串

六、最长无重复子数组

七、盛水最多的容器

八*、接雨水


一、合并两个有序的数组

合并两个有序的数组_牛客题霸_牛客网

本来还想着建一个新数组,最后按顺序赋值给A

其实只需要倒过来赋值就行了

class Solution {
public:
    void merge(int A[], int m, int B[], int n) {
        int index=m+n-1,cur1=m-1,cur2=n-1;
        while(cur1>=0&&cur2>=0)
        {
            if(A[cur1]>B[cur2])
            {
                A[index--]=A[cur1--];
            }
            else{
                A[index--]=B[cur2--];
            }
        }
        //cur1不用判断了
        while(cur2>=0)A[index--]=B[cur2--];
    }
};

二、判断是否为回文字符串

判断是否为回文字符串_牛客题霸_牛客网

人机题

class Solution {
public:
    bool judge(string str) {
        int left=0,right=str.size()-1;
        while(left<right)
        {
            if(str[left]!=str[right])return false;
            ++left;
            --right;
        }
        return true;
    }
};

三、合并区间

合并区间_牛客题霸_牛客网

/**
 * struct Interval {
 *	int start;
 *	int end;
 *	Interval(int s, int e) : start(start), end(e) {}
 * };
 */
#include <vector>
class Solution {
public:
    struct cmp
    {    
        bool operator()(Interval&I1,Interval&I2)
        {
            return I1.start<I2.start;
        }
    };
    vector<Interval> merge(vector<Interval>& intervals) {
        int n=intervals.size();
        if(n==0||n==1)return intervals;
        sort(intervals.begin(),intervals.end(),cmp());
        int right=1,begin=intervals[0].start,end=intervals[0].end;
        vector<Interval> ret;
        while(right<n)
        {
            //符合合并条件,处理begin,end
            while(right<n&&intervals[right].start<=end)
            {
                //end为区间右边的最大值
                end=max(end,intervals[right].end);
                ++right;
            }
            //合并
            ret.push_back(Interval(begin,end));
            //防止访问越界
            //更新新的开头,末尾
            if(right!=n)
            {
                begin=intervals[right].start;
                end=intervals[right].end;
            }
        }
        return ret;
    }
};

四、最小覆盖子串

最小覆盖子串_牛客题霸_牛客网

滑动窗口

#include <climits>
#include <unordered_map>
class Solution {
public:
    string minWindow(string S, string T) {
        if(S.size()<T.size())return "";
        int left=0,right=0,n=S.size();
        unordered_map<char, int> hashS;
        unordered_map<char, int> hashT;
        //哈希表记录需要匹配的字符,及其对应数量
        for(auto&ch:T)
        {
            hashT[ch]++;
        }
        int begin=-1,len=INT_MAX,count=0;    //记录匹配字符数量
        while(right<n)
        {
            //【right】入窗口
            char in=S[right];
            if(++hashS[in]<=hashT[in])++count;
            //当完全匹配时,我们再窗口中找最短子串
            while(count==T.size())
            {
                if(right-left+1<len)
                {
                    len=right-left+1;
                    begin=left;
                }
                //【left】出窗口
                char out=S[left++];
                if(hashS[out]--<=hashT[out])--count;
            }
            //别忘记更新right
            ++right;
        }
        //如果begin没有更新,返回空串,否则返回最小覆盖子串
        return begin==-1?"":S.substr(begin,len);
    }
};

五、反转字符串

反转字符串_牛客题霸_牛客网

人机题

#include <iterator>
class Solution {
public:
    string solve(string str) {
        reverse(str.begin(),str.end());
        return str;
    }
};

六、最长无重复子数组

最长无重复子数组_牛客题霸_牛客网

滑动窗口

#include <unordered_map>
#include <vector>
class Solution {
public:
    int maxLength(vector<int>& arr) {
        int left=0,right=0,n=arr.size(),len=0;
        if(n==0||n==1)return n;
        unordered_map<int, int> hash;
        while(right<n)
        {
            int in_num=arr[right];
            hash[in_num]++;
            //出现次数只能为1
            while(hash[in_num]>1)
            {
                int out_num=arr[left++];
                hash[out_num]--;
            }
            len=max(len,right-left+1);
            ++right;
        }
        return len;
    }
};

七、盛水最多的容器

盛水最多的容器_牛客题霸_牛客网

贪心+双指针

class Solution {
public:
    int maxArea(vector<int>& height) {
        int n=height.size();
        if(n==0||n==1)return 0;

        int left=0,right=n-1,H,S=0;
        while(left<right)
        {
            H=min(height[left],height[right]);
            S=max(S,H*(right-left));
            //从小的那段开始,往内找,跳过更小的
            if(height[left]<height[right])
            {
                int num=height[left];
                while(left<right&&height[left]<=num)++left;
            }
            else {
                int num=height[right];
                while(left<right&&height[right]<=num)--right;
            }
        }
        return S;
    }
};

八*、接雨水

接雨水问题_牛客题霸_牛客网

双指针,开始指向数组两端。从小端开始,往内找,找到<=的就是底,sum+=(小端的高-底的高)如果遇到更大的就更新小端为更大值

class Solution {
public:
    long long maxWater(vector<int>& arr) {
        int n=arr.size();
        if(n<=2)return 0;
        int left=0,right=n-1,H;
        long long sum=0;
        while(left<right)
        {
            if(arr[left]<arr[right])
            {
                H=arr[left];
                while(left<right)
                {
                    ++left;
                    if(arr[left]<=H)sum+=(H-arr[left]);
                    else{
                        H=arr[left];
                        break;
                    }
                }
            }
            else{
                H=arr[right];
                while(left<right)
                {
                    --right;
                    if(arr[right]<=H)sum+=(H-arr[right]);
                    else{
                        H=arr[right];
                        break;
                    }
                }
            }
        }
        return sum;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_dindong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值