【算法】滑動窗口


滑動窗口

1.概念

滑動窗口是一類很常見的題型,最常見的就是子串問題,因為滑動窗口是一個連續的,所以很容易就是問滿足條件的最大或者最小子串啊,這個條件就是不同的地方,但萬變不離其宗,滑動窗口就是一個窗口的移動。

總之:子串+最值 --> 滑動窗口

滑動窗口有兩大類

  • 固定長度的滑動窗口:窗口的大小是固定好的,這是其實分為了窗口形成和人窗口滑動兩個過程,窗口形成就是要先讓窗口達到要求的長度; 窗口滑動的過程在右邊界長的時候,左邊界也要跟着長,維持窗口長度不變;
  • 可變長度的滑動窗口:這也是遇到最多的,控制窗口移動的原因不是長度,而是是否達到題目中某一條件,如果達到此條件,那右邊界停下,左邊界開始移動,試圖去破壞這一條件,就是在這個過程中不斷的更新結果。

2.過程

  • 1.從題目中先整理出條件,常見的比如說子序列的和大於某值,子串中包含某些值,子串中出現了重復值,先把這些條件找出來,這就是用來移動窗口的依據;
  • 2.初始化left和right指針都為0,right指針從頭走到尾,當不滿足上面的條件時,right走,一直走到這個窗口滿足上面我們總結出來的條件了,停下;
  • 3.記錄下我們要的答案,比如最典型的問子串的最小長度啊啥的,記錄下這時候我們的right-left+1,這就是目前窗口的大小;
  • 4.右邊走不動了那左邊就得開始走了,移動左指針,每次移動都要把左指針的值給去除,因為我們統計的結果只能是窗口里的結果,出去了自然就不要了,然后,每一次左指針的移動都要判斷是否滿足條件,比如要求子串和大於某一值,左邊移動一步,減去這個值看還大於目標值嗎,如果滿足,更新我們最終要的最小子串,因為這時候子串長度肯定縮小了嘛,直到不滿足條件為止;如果不滿足,那左指針不用再動了,右指針可以開始動了,尋找下一個滿足條件時停下來。
  • 5.就這樣重復,右邊動完左邊動,左邊動完右邊再動;

總結:右邊界要使窗口達到某一條件,左邊界使窗口跳出這一條件

3.模板

int left = 0, right = 0;
while(right < nums.length){
    result = result + nums[right]; 
    //更新窗口內數據;
    //將移入窗口的值添加進結果,這里就是不同題目不同要求;比如和,比如哈希表等;   
    while(判斷是否達到條件){  //如果達到條件左窗口就要收縮了;
        res = Math.min(res, right-left+1); //只要滿足條件每次都要更新答案;
        //更新窗口內數據;
        result = result - nums[left]; //左窗口的值從結果去除;
        left++; //左窗口移動;
    }
    right++;  //只要不滿足條件右窗口移動;
}

其實,我們的右邊界就是在努力滿足條件,找到一個可行解,而我們的左邊界呢,想讓這個可行解更好一點,比如長度更短一下,是在尋找一個更好的最優解,但是很可能玩脫了不滿足條件。

在套模板的時候我們需要思考以下問題:

  • 1.當移動right,即加入結果的時候,需要更新哪些數據;
  • 2.到達什么條件時,窗口停止擴大,也就是右邊界停下來,開始左邊界移動,縮小窗口;
  • 3.當移動left,即移出結果的時候,需要更新哪些數據;
  • 4.要的最后答案應該在窗口擴大還是窗口縮小時更新;

4.樣例

3. 無重復字符的最長子串

209. 長度最小的子數組

劍指 Offer 59 - I. 滑動窗口的最大值

424. 替換后的最長重復字符

5.體會

  • 要能夠根據題目要求找到條件,因為條件是指揮我們移動左窗口還是右窗口的長官,不滿足條件,右窗口移動; 滿足條件,左窗口移動;
  • 要始終清楚左右兩個邊界都是不會回退的,都是朝着最后走的,不可能會出現往回走的時候;
  • 兩個窗口不會同時移動,每次只有兩個窗口中的一個移動。
  • 換種思路:我們的窗口滑動其實就是一個雙端隊列。當不滿足條件時,數組元素依次從隊尾入隊;當滿足條件時,隊首元素出隊;所以有的時候去想象成一個隊列,可能會更好的理解;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM