滑动窗口,一套模板秒杀leetcode算法题

滑动窗口的代码模板

#window表示当前窗口
unordered_map<char,int> window;
#need表示窗口可以移动时需要满足的条件,某些情况下可以不写
unordered_map<char,int> need;
#fast指向当前window的右边界,slow指向window的左边界,区间左闭右开
int fast=0,slow=0;
#valid记录window中满足need的个数
int valid=0;
#更新need
for(auto i:t)
    need[i]++;
while(fast<s.size()){
    char c=s[fast];
    //s[fast]加入window后,fast立刻++,这里说明window是左闭右开的
    fast++;
    if(need.count(c)){
        window[c]++;
        if(window[c]==need[c])
        valid++;
    }
    #valid的大小等于need.size(),说明当前window已经满足条件
    while(valid==need.size()){
        if(满足题意){
           ...
        }
        #更新窗口数据
        char c=s[slow];
        slow++;
        if(need.count(c)){
            if(window[c]==need[c])
                valid--;
            window[c]--;
        }
    }
}

以上代码都是固定的,需要改动的部分都在 ... 处,下面我们结合具体的题目来看一下。

以leetcode上的例题为例,按照输入个数分为两类

1、两个输入:

438. 找到字符串中所有字母异位词

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        unordered_map<char,int> need;
        unordered_map<char,int> window;
        vector<int> ans;
        for(auto i:p)
            need[i]++;
        int valid=0,fast=0,slow=0;
        while(fast<s.size()){
            char f=s[fast];
            fast++;
            if(need.count(f)){
                window[f]++;
                if(window[f]==need[f])
                    valid++;
            }
            while(valid==need.size()){


                //当下面条件成立时,说明当前窗口内的是异位词,需添加到ans中
                if(fast-slow==p.size())
                    ans.push_back(slow);


                char str=s[slow];
                slow++;
                if(need.count(str)){
                    if(need[str]==window[str])
                        valid--;
                    window[str]--;
                }
            }
        }
        return ans;
    }
};

567. 字符串的排列

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        unordered_map<char,int> window;
        unordered_map<char,int> need;
        for(auto i:s1)
            need[i]++;
        int fast=0,slow=0,valid=0;
        while(fast<s2.size()){
            char c=s2[fast];
            fast++;
            if(need.count(c)){
                window[c]++;
                if(window[c]==need[c])
                    valid++;
            }
            while(valid==need.size()){
/
                
                if(fast-slow==s1.size())
                    return true;


                char d=s2[slow];
                slow++;
                if(need.count(d)){
                    if(window[d]==need[d])
                        valid--;
                    window[d]--;
                }
            }
        }
        return false;
    }
};

LCR 014. 字符串的排列

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        unordered_map<char,int> window;
        unordered_map<char,int> need;
        for(auto i:s1)
            need[i]++;
        int fast=0,slow=0,valid=0;
        while(fast<s2.size()){
            char c=s2[fast];
            fast++;
            if(need.count(c)){
                window[c]++;
                if(window[c]==need[c])
                    valid++;
            }
            while(valid==need.size()){


                if(fast-slow==s1.size())
                    return true;


                char d=s2[slow];
                slow++;
                if(need.count(d)){
                    if(window[d]==need[d])
                        valid--;
                    window[d]--;
                }
            }
        }
        return false;
    }
};

76. 最小覆盖子串

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char,int> window;
        unordered_map<char,int> need;
        int fast=0,slow=0,start=0,len=INT_MAX,valid=0;
        for(auto i:t)
            need[i]++;
        while(fast<s.size()){
            char c=s[fast];
            fast++;
            if(need.count(c)){
                window[c]++;
                if(window[c]==need[c])
                    valid++;
            }
            while(valid==need.size()){
///

                if(len>fast-slow){
                    len=fast-slow;
                    start=slow;
                }

///
                char c=s[slow];
                slow++;
                if(need.count(c)){
                    if(window[c]==need[c])
                        valid--;
                    window[c]--;
                }
            }
        }
        return INT_MAX==len?"":s.substr(start,len);
    }
};

2、一个输入

一个输入相较于两个输入比较简单,因为不需要通过need来判断当前window是否需要移动

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char,int> window;
        int fast=0,slow=0,ans=0;
        while(fast<s.size()){
            char c=s[fast];
            fast++;
            window[c]++;
            //window[c]>1说明当前window内有重复元素,需要移除,来保证window内的元素都是唯一的
            //这时,window就需要移动
            while(window[c]>1){
                window[s[slow]]--;
                slow++;
            }
            //当前window内的元素都是唯一的,可以更新ans
            ans=max(ans,fast-slow);
        }
        return ans;
    }
};

904. 水果成篮

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        unordered_map<int,int> window;
        int fast=0,slow=0,count=0;
        while(fast<fruits.size()){
            int c=fruits[fast];
            fast++;
            window[c]++;
            //说明window里有超过两种元素,窗口需要滑动,slow需要向右移动
            while(window.size()>2){
                int d=fruits[slow];
                window[d]--;
                if(window[d] == 0 )
                    window.erase(d);
                slow++;
            }
            count=max(count,fast-slow);
        }
        return count;
    }
};

209. 长度最小的子数组

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int ans=INT_MAX;
        int fast=0,slow=0;
        //记录窗口内元素总和
        int sum=0;
        while(fast<nums.size()){
            sum+=nums[fast];
            fast++;
            while(sum>=target){
                ans=min(ans,fast-slow);
                sum-=nums[slow];
                slow++;
            }
        }
        return ans==INT_MAX?0:ans;
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值