(轉)leetcode:Find All Anagrams in a String 滑動視窗方法總結
今天做了幾道滑動視窗的題,稍微總結一下。
起因源於早上在leetcode上pick one,隨機到了一個easy的題目,想著隨便做了,結果半天也找不到最優解,耗時300多ms,A是A了,不過就是暴力罷了。
題目是:Find All Anagrams in a String,連結在https://leetcode.com/problems/find-all-anagrams-in-a-string/ ,題目就不過多解釋了。
採用的方法是滑動視窗的方法,可以說這基本是一類方法,leetcode上有幾道題都可以用相同的思想,有點類似動態規劃,在大致思想步驟一致的前提下,每個題有各自不同的“條件式”。
滑動視窗思想
滑動視窗,就是利用雙指標技巧,以及map資料結構,維護一個不斷擴充套件、伸縮的視窗,在視窗內探測記錄我們感興趣的結果。比如這道題目,以用例分析:
Input:
s: “cbaebabacd” p: “abc”
Output:
[0, 6]
首先,先構造一個map,對於p中的每個字元char,都有map[char]++。
然後,初始化一個長度為0的視窗,left = 0,right = 0。第一步先擴充套件視窗,也就是在right的右邊界上做文章。每次right讀到一個字元char,都有map[char]–。當map[char]的值大於等於1時,很明顯就是視窗中進入了一個p中含有的字元。我們可以取一個變數count,值為p中所有字元的總數。每次有一個p中字元進入視窗,則count–。這樣,當count == 0的時候,表明我們的視窗中包含了p中的全部字元,得到一個結果。
當視窗包含一個結果以後,為了進一步遍歷,我們需要縮小視窗使視窗不再包含全部的p,同樣,如果map[char]>=0,表明一個在p中的字元就要移除視窗,那麼count ++,以此類推。
最終程式碼如下:
public class Solution {
public List<Integer> findAnagrams(String s, String p) {
ArrayList<Integer> result = new ArrayList<>();
if(s == null || p == null) return result;
int left = 0,right =0,count = p.length();
int[] map = new int[256];
char[] sc = s.toCharArray();
for (char c : p.toCharArray()) map[c] ++;
while (right < s.length()) {
if (map[sc[right++]]-->=1) count --;
if (count == 0) result.add(left);
if (right - left == p.length() && map[sc[left++]]++ >=0) count++;
}
return result;
}
}
方法小結
可以說滑動視窗這種思想,關鍵點在於:
1、map中儲存值的意義
2、視窗什麼時候擴充套件和收縮,對應於left和right值什麼時候發生變化。
在解題的時候,首先嚐試擴充套件視窗right,看看什麼時候包含了一個結果,記錄結果。然後縮小左邊界left,直到視窗不在包含一個可能解!接著就可以繼續擴充套件視窗了,以此類推。
由此,可以得到一個模板:
public class Solution {
public List<Integer> findAnagrams(String s, String p) {
ArrayList<Integer> result = new ArrayList<>();
if(s == null || p == null) return result;
int left = 0,right =0,count = p.length();
int[] map = new int[256];
char[] sc = s.toCharArray();
//初始化map
for (char c : p.toCharArray()) map[c] ++;
while (right < s.length()) {
//1:擴充套件視窗,視窗中包含一個T中子元素,count--;
//2:通過count或其他限定值,得到一個可能解。
//3:只要視窗中有可能解,那麼縮小視窗直到不包含可能解。
}
return result;
}
}
比如leetcode另一個題目 Minimum Window Substring:https://leetcode.com/problems/minimum-window-substring/。
用例是:
S = “ADOBECODEBANC”
T = “ABC”
Minimum window is “BANC”.
瞭解了第一道題目以後,這道題目也很容易思考出來。解題時,按照步驟:
- 擴充套件視窗,視窗中包含一個T中子元素,count–;
- 通過count或其他限定值,得到一個可能解。
- 只要視窗中有可能解,那麼縮小視窗直到不包含可能解。
首先,維護一個map,一個視窗。先看右邊界,當視窗擴充套件包含全部ABC時停下,這個時候必然有count == 0。但是,這個時候的結果字串可能很長,所以我們要接著縮小左邊界。同時,當count == 0時,我們要一直縮小左邊界以找到更短的字串。慢慢count>0了,表明視窗中不包含全部的T了,那麼又要擴充套件視窗。依次類推,最終找到最短字串。
套用模板,程式碼如下:
public class Solution {
public String minWindow(String s, String t) {
int[] map = new int[256];
int left = 0,right = 0,count = t.length(), minLen = Integer.MAX_VALUE;
String result = "";
for (char tc : t.toCharArray()) map[tc]++;
char[] sc = s.toCharArray();
while (right < s.length()|| count ==0) {
if (count == 0){
if (right-left+1<minLen){
minLen = right - left +1;
result = s.substring(left,right);
}
if (map[sc[left++]]++>=0) count++;
}else {
if ( map[sc[right++]]-->=1) count--;
}
}
return result;
}
}
https://leetcode.com/problems/longest-repeating-character-replacement/
也是一道滑動視窗的題,在解決諸如substring這類問題時,不妨嘗試想一想滑動視窗。
相關文章
- LeetCode 438. Find All Anagrams in a StringLeetCode
- 滑動視窗問題總結
- 滑動視窗相關的題目總結
- 滑動視窗(Sliding Window)技巧總結
- 滑動視窗法——Leetcode例題LeetCode
- 「LeetCode Top100」之滑動視窗LeetCode
- Sentinel 原理-滑動視窗
- 細聊滑動視窗
- LeetCode 239. 滑動視窗最大值LeetCode
- 滑動視窗演算法演算法
- 【完虐演算法系列】「字串 – 滑動視窗」覆盤總結演算法字串
- Leetcode 最小調整數+滑動視窗遞增子序列LeetCode
- LC演算法技巧總結(二):雙指標和滑動視窗技巧演算法指標
- TCP 流量控制-滑動視窗TCP
- 滑動視窗演算法思路演算法
- Sentinel滑動視窗演算法演算法
- 滑動視窗分析SQL實踐SQL
- 滑動視窗與雙指標指標
- Flink的滾動視窗、會話視窗、滑動視窗及其應用會話
- mysql視窗函式中的滑動視窗MySql函式
- 自己實現一個滑動視窗
- 力扣刷題-滑動視窗(字串)力扣字串
- Sentinel Go 核心統計結構滑動視窗的深度解析Go
- WeetCode2滑動視窗系列
- 239. 滑動視窗最大值
- TCP的滑動視窗和擁塞控制TCP
- [Leetcode]雙項佇列解決滑動視窗最大值難題LeetCode佇列
- leetcode刷題記錄:演算法(三)滑動視窗演算法LeetCode演算法
- Hive實戰—時間滑動視窗計算Hive
- 氣球遊戲騰訊面試題滑動視窗解法遊戲面試題
- 【演算法】滑動視窗三步走演算法
- 滑動視窗最大值的golang實現Golang
- 滑動視窗法——子串相關問題
- [Python手撕]滑動視窗最大值Python
- 滑動視窗最大值——棧與佇列佇列
- Leetcode AnagramsLeetCode
- Leetcode 題解系列 -- 和為s的連續正數序列(滑動視窗)LeetCode
- Leetcode 442. Find All Duplicates in an ArrayLeetCode