Sliding Window Algorithm(滑动窗口算法)分析与实践

学习如何使用Sliding Window Algorithm 攻克相关的Leetcode算法题。Leetcode上有若干滑动窗口问题,网络协议上也广泛使用了滑动窗口算法,可见这个算法的重要性。

本文参考:
1.https://leetcode.com/problems/find-all-anagrams-in-a-string/discuss/92007/Sliding-Window-algorithm-template-to-solve-all-the-Leetcode-substring-search-problem.
2.https://stackoverflow.com/questions/8269916/what-is-sliding-window-algorithm-examples
3.http://www.codingalpha.com/sliding-window-algorithm-c-program/


什么是滑动窗口算法?
The Sliding Problem contains a sliding window which is a sub – list that runs over a Large Array which is an underlying collection of elements.

假设有数组[a b c d e f g h]
一个大小为3的滑动窗口在其上滑动,则有:
[a b c]
  [b c d]
    [c d e]
      [d e f]
        [e f g]
          [f g h]

滑动窗口算法对比与分析
——待添加


滑动窗口问题实例
一、FInd All Anagrams in a String

分析:对于string s 和 string t,查找s中t的同字母异序词子序列。那么这个子序列很明显有三点非常明显的特征:

  • 是s的子序列

  • 包含t中所包含的全部字符(包括重复的)

  • 子序列长度与t相同

我们实现算法的最终目标就是:判断以上三个条件是否成立。

条件1和条件3无疑很好判断,但对于条件2,如果使用嵌套循环的方式暴力解决,时间复杂度将是O(n*m).n为s的规模,m为t的规模。

而滑动窗口算法就是为了能够高效的判断该条件。

思路:在s上伸缩滑动一个窗口,(注意,不止包括整体的滑动——即左右边界同方向相同距离移动,也包括伸缩——即一个边界动一个边界不动),那么必然满足条件1,接下来如果由该窗口得到的子序列满足条件2,且满足条件3,那么保存窗口左边界作为结果之一。然后,继续伸缩滑动窗口,直至得到全部结果。

具体来说:

  1. 双指针begin,end——记录滑动窗口的左右边界。

  2. 一个Hash表——记录的t中的所有字符(去重)以及每个字符的出现次数。原因:由于t中可能包含重复字符,那么不仅要依次判断窗口子序列是否包含t中某个字符,还要判断该字符出现的次数是否与在t中相同。既然字符本身和出现次数相关联,那么就可以用一对键值对来表示,所以可使用Hash表来保存t中的字符和出现频率。C++中,我们用unordered_map<char, int> map;

  3. 一个计数器count,记录t中包含的字符数(去重后),即需要判断是否存在于t的字符。

  4. 令begin = 0, end = 0;移动右边界,每当发现一个字符存在于t中,递减该字符在Hash表中出现频次,即<key,value>中value的值,递减至0时,说明该窗口子序列中至少包含了与t中相同个数的该字符,那么此时递减count计数器,表示该字符的判断已完成,需要判断的字符数-1.

  5. 以此类推,不断拓展右边界,直至count为0,表示窗口序列中已经至少包含了t中所有字符(包括重复的)。

  6. 分析此时的窗口子序列,t是该序列的子集,条件2已满足。如果两者长度相同,即满足条件3,那么它的左边界begin就是我们想要的结果之一了。但我们不会一直那么幸运,这时就需要收缩窗口的左边界,即end不动,begin向右移动遍历该子序列,直至找到t中包含的字符,此时再次计算end-begin的值,与t长度比较,判断是否是想要的结果。而找到上述字符后,字符频次加1,如加1后该字符频次仍小于0,说明该字符有冗余,而出现频次大于0,则count加1,这是告诉我们有一个字符需要重新被判断了,因为无论它是不是我们想要的,都不能再用了,需要继续向右拓展窗口从新找起。

  7. 当count != 0时,继续向右拓展窗口,直至count为0,然后判断条件3的同时,向右移动begin遍历子序列,直至count != 0,以此类推。

(为了弄清思路的细节,写了一大堆的文字,实在是辛苦。)

上面是文字形式的分析,如果看不懂,那么应结合图表推演分析。且真正分析算法问题时,应该在脑中或者草稿纸上构思出具体的图画。

//该例子来自于leetcode
Input:
s: "cbaebabacd" p: "abc"
Output:
[0, 6]

Explanation:
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".
滑动窗口序列变化示意图
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        
        vector<int> result;
        
        if(s.empty() || p.empty()) return result;
        if(p.size() > s.size()) return result;
        
        unordered_map<char, int> map;
        
        for(char c : p)
        {
            map[c] = map[c] + 1;
        }
        
        size_t count = map.size();
        
        int begin = 0, end = 0;
        
        while(end < s.size())
        {
            if(map.find(s.at(end)) != map.end())
            {
                map[s.at(end)]--;
                if(map[s.at(end)] == 0){ count--; }
            }
            ++end;
            
            while(count == 0)
            {
                if(map.find(s.at(begin)) != map.end())
                {
                    map[s.at(begin)]++;
                    if(map[s.at(begin)] > 0){ count++; }
                }
                
                if(end - begin == p.size())
                {
                    result.push_back(begin);
                }
                ++begin;
            } 
        }
        
       return result;
        
    }
};

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • 依稀记得去年元宵,我跟家里的那个人吵架了,我一个人赌气跑到街上,和着眼泪吃完了一碗元宵。然后悻悻地回到了家。今年无...
    我的抠脚大汉阅读 192评论 0 0
  • 这夜在顺德佬还没把菜吃完,一个个就喊吃撑了。恰巧还有两个居然赶到,来担那消灭残羹的重任。 不过也只是给一个留了菜,...
    枫岭旧客阅读 371评论 2 3
  • 问题背景 —— 一位陷入两难困境的大学生朋友说:因高中懒散,只考取了普通一本,现就读于国内非211学校的金融系。自...
    上官文商阅读 1,323评论 1 4
  • 前言 在iOS开发中,由于各个屏幕宽度不一样,所以适配起来多少有些麻烦。本文,先介绍一下适配方法,然后介绍一下这个...
    David_Cap阅读 2,526评论 10 26