滑動窗口
1.概念
滑動窗口是一類很常見的題型,最多見的就是子串問題,由於滑動窗口是一個連續的,因此很容易就是問知足條件的最大或者最小子串啊,這個條件就是不一樣的地方,但萬變不離其宗,滑動窗口就是一個窗口的移動。html
總之:子串+最值 --> 滑動窗口數組
滑動窗口有兩大類指針
- 固定長度的滑動窗口:窗口的大小是固定好的,這是其實分爲了窗口造成和人窗口滑動兩個過程,窗口造成就是要先讓窗口達到要求的長度; 窗口滑動的過程在右邊界長的時候,左邊界也要跟着長,維持窗口長度不變;
- 可變長度的滑動窗口:這也是遇到最多的,控制窗口移動的緣由不是長度,而是是否達到題目中某一條件,若是達到此條件,那右邊界停下,左邊界開始移動,試圖去破壞這一條件,就是在這個過程當中不斷的更新結果。
2.過程
- 1.從題目中先整理出條件,常見的好比說子序列的和大於某值,子串中包含某些值,子串中出現了重複值,先把這些條件找出來,這就是用來移動窗口的依據;
- 2.初始化left和right指針都爲0,right指針從頭走到尾,當不知足上面的條件時,right走,一直走到這個窗口知足上面咱們總結出來的條件了,停下;
- 3.記錄下咱們要的答案,好比最典型的問子串的最小長度啊啥的,記錄下這時候咱們的right-left+1,這就是目前窗口的大小;
- 4.右邊走不動了那左邊就得開始走了,移動左指針,每次移動都要把左指針的值給去除,由於咱們統計的結果只能是窗口裏的結果,出去了天然就不要了,而後,每一次左指針的移動都要判斷是否知足條件,好比要求子串和大於某一值,左邊移動一步,減去這個值看還大於目標值嗎,若是知足,更新咱們最終要的最小子串,由於這時候子串長度確定縮小了嘛,直到不知足條件爲止;若是不知足,那左指針不用再動了,右指針能夠開始動了,尋找下一個知足條件時停下來。
- 5.就這樣重複,右邊動完左邊動,左邊動完右邊再動;
總結:右邊界要使窗口達到某一條件,左邊界使窗口跳出這一條件。code
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++; //只要不知足條件右窗口移動;
}
其實,咱們的右邊界就是在努力知足條件,找到一個可行解,而咱們的左邊界呢,想讓這個可行解更好一點,好比長度更短一下,是在尋找一個更好的最優解,可是極可能玩脫了不知足條件。htm
在套模板的時候咱們須要思考如下問題:blog
- 1.當移動right,即加入結果的時候,須要更新哪些數據;
- 2.到達什麼條件時,窗口中止擴大,也就是右邊界停下來,開始左邊界移動,縮小窗口;
- 3.當移動left,即移出結果的時候,須要更新哪些數據;
- 4.要的最後答案應該在窗口擴大仍是窗口縮小時更新;
4.樣例
3. 無重複字符的最長子串隊列
209. 長度最小的子數組get
劍指 Offer 59 - I. 滑動窗口的最大值模板
424. 替換後的最長重複字符統計
5.體會
- 要可以根據題目要求找到條件,由於條件是指揮咱們移動左窗口仍是右窗口的長官,不知足條件,右窗口移動; 知足條件,左窗口移動;
- 要始終清楚左右兩個邊界都是不會回退的,都是朝着最後走的,不可能會出現往回走的時候;
- 兩個窗口不會同時移動,每次只有兩個窗口中的一個移動。
- 換種思路:咱們的窗口滑動其實就是一個雙端隊列。當不知足條件時,數組元素依次從隊尾入隊;當知足條件時,隊首元素出隊;因此有的時候去想象成一個隊列,可能會更好的理解;