滑动窗口(一般用于连续子数组或者子字符串)

一定要记住连续,连续:

做到这我只能说labuladong的那个算法题目给的真的精辟,当然leecode上的大佬的题解也是很牛逼的;下面我们一起来看看我们滑动窗口一般的思路;

因为是窗口嘛,一定是一个矩形,所以肯定是连续的,一般都是我们执行连续的窗口操作,但是有时候,题目不一定会明确的指出,这需要我们自己做判断,当然,整个滑动窗口还是非常的有规律的,其中使用的unordered_map的次数非常非常的多,还有一些细节需要把握的很好,不然就不容易AC,这是应该要注意的!下面一起来看看题目吧!

1.

 覆盖最小字串的问题,这需要我们判断,首先这是一个对于子字符串的操作,同时还必须是连续的;因此我们可以断定,可以使用我们的滑动窗口,那么我们应该怎么用呢?先上模板:

while(right<num.size()){

        向右移动一格;

        更新数据;

        while(左指针可以向右移动了||需要向左移动了){

              向右移动一格;

        更新数据;

        }

}

基本就是这样的一个模板框架:我们先来看我们上面的这道题:

首先我们应该把所有的模板字符串存到我们的Map<char,int>中,char代表的是我们存的字符,int代表的是我们该字符的个数 for(char a, p) Map[a]++;这样一个操作即可;然后我们此时就需要对全局进行看待了,首先我们如果右指针向右走,那么我们的需要的该字符串肯定要--;如果我们需要的某个字符串的Map[a]==0,

那么这个时候我们就可以让我们的valcount++;valcount++记录的是有效的字符串的个数;比如我们呢现在是匹配"AABC";那么当我们的去匹配的字符串中有两个A时,我们的valcount++;那么我们时候时候去缩小我们的窗口呢,就是当我们的valcount==Map.size()的时候,

 

但是,这里有一点,尤其要注意,我们的Map假如你没有对他进行Map[a]++,或者--;只是使用了if(Map[a]==0)那么此时的Map的size也会发生变化,因此我们最好一开始就把我们的Map的size存下来,但是使用Map.count(a)就不会使他发生变化,有点乱了,记住就好,然后如果我们缩小窗口的话,加入我们的Map[left]所需要的字符>0了;证明我们的去匹配的串已经不符合要求了这时候,就需要我们再去扩大我们的滑动窗口,同时我们应该在条件符合的情况下,去计算我们的最大的或者最小的长度,一般是使用RIGHT-LEFT+1;加1或者其他操作要具体而定;

 

2.

 这个题目的话,使用的还是我们的Map,unordered_map还是非常非常好用的;

基本框架还是一样的,如果我们对右指针扩大的话;那么我们的Map[s[right]]++;那么我们加入之后看看是否需要shrink呢,就是看看我们的Map[s[right]]>1;如果大于1;那就肯定需要:

直到他的数目最多为1;那么这个时候我们的滑动窗口就能够达到最终的目的;然后在符合条件的情况下,进行长度的判断;

3.下面两个题:我最开始做的时候,不知道什么问题,做了一晚上,没做出来,第二天来了,接着就做出来了,感觉也不是很难,但是不知道为什么没做对,可能是没领悟透彻 

 感觉这个题的唯一的一个混乱点就是我们的最后的长度必须是相同的,就是我们的子串和我们的p的长度必须是相同的,只能这样我们才能够找到最终的结果;那么我们应该怎么写呢;我感觉还是要增加一点,就是我们valcount这个数值是指我们当前满足条件的字符的个数,而我们右指针移动的时候,我们的valcount肯定是可能增加的,不可能是减少的,加入我们需要一个a,但是我们的字串中有了两个a,也不必把我们的valcount减去一个1;我们我们最终的约束条件是valcount满足的条件下,我们right-left+1==p.size();

 所以不必过于担心我们valcount的事情,同时我们我们应该意识到,如果我们缩小了窗口,把我们所需要的字符给缩小没有了,那么我们肯定要valcount--;这里一定要注意我们的临界点的问题,是大于还是小于还是等于,我们Map存储的是我们需要的字符的数字,如果我们删除了那些无关紧要的字符,最终他们的个数肯定最多为0,假如我们删去了那些我们需要的字符,那么我们的需要的个数,肯定就>1了,因此这就是判断条件:

 最后再总结一个:有点累了:就是从两边到中间的情况;

第一眼看到这个题,什么呀,和滑动窗口哪有关系,说实话我看了题解之后,也是脑壳很昏,真的看不懂这是什么东西,怎么说的牛头不对马嘴,后面才知道,这个题目时让我们把左右边的数字去掉,那不就是让我们去中间的一段连续的子字符串嘛,如果想到这那就好说了,而且这个模板比那么模板可以说更简单。

先把所有的nums[i]相加-count = sum; 只要中间的一段数组等于sum,我们得到最长的那段数字;剩下的就是最短的操作数,因为我们要的是整数嘛;就是刚刚好的数字,如果不是的话,我们是不会要的,右指针右移,那么我们的n+=nums[right];

count+=nums[right]; 

 然后如果我们的count>sum了,那么证明我们的那个数组加多了,需要缩短

while(count>sum){

                count-=nums[left];

                left++;

            }

直至小于或者等于;如果等于那么这就是我们所需要的一段子数组呀 

 if(count==sum)

            maxlength = max(maxlength,right-left+1);

            right++;

 最终我们使用nums.size()-maxlength;得到最小的操作数;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值