扒一扒滑動視窗演算法的褲子

2021-10-07 10:18:04 字數 4597 閱讀 8115

目錄

1、演算法框架

2、leetcode76.最小覆蓋子串

3、leetcode567.字串的排列

4、leetcode438.找到字串中所有字母異位詞

5、leetcode3.無重複字元的最長子串

int left = 0, right = 0;

while (right < s.size())

}

這個演算法技巧的時間複雜度是 o(n),比字串暴力演算法要高效得多。演算法的思路不難,難的是各種細節問題。比如說如何向視窗中新增新元素,如何縮小視窗,在視窗滑動的哪個階段更新結果。即便你明白了這些細節,也容易出 bug,找 bug 還不知道怎麼找,真的挺讓人心煩的。完整演算法框架如下:

/* 滑動視窗演算法框架 */

void slidingwindow(string s, string t)

int left = 0, right = 0;

int valid = 0;

while (right < s.size())

}}

其中兩處 ... 表示的更新視窗資料的地方,到時候你直接往裡面填就行了。而且,這兩個 ... 處的操作分別是右移和左移視窗更新操作,操作是完全對稱的。

給你乙個字串 s、乙個字串 t,請在字串 s 裡面找出:包含 t 所有字元的最小子串。

示例:

輸入: s = "adobecodebanc", t = "abc"

輸出: "banc"

說明:1、如果 s 中不存這樣的子串,則返回空字串""。2、如果 s 中存在這樣的子串,我們保證它是唯一的答案。

演算法:

1、用hashmap表快取文字串 s、模式串 t 的內容,用乙個變數 curvaildcnt 來表示兩個表中字元匹配的個數。

2、首先用 checkmap 記錄t中的所有字元(key)及其個數(value)

3、向右滑動視窗 right++,當出現 checkmap中的字元 ch 時,需要用 slidewinmap 儲存,

判斷該字元 ch 的個數是否已經和 checkmap 中的相等,相等則計數curvaildcnt++;

4、當 slidewinmap 中所有的字元均以匹配 checkmap 中的字元,即 curvaildcnt == check.keyset().size(),

對於表中任一字元均有slidewinmap.get(ch) >= checkmap.get(ch),此時滿足條件,開始迴圈視窗的左側。

4.1、更新視窗範圍,左右側邊界

4.2、從左側收縮視窗left++,當出現匹配字元 ch 時,需要從滑動視窗中減去其個數,當 ch 的個數不在匹配時則需要將

curvaildcnt--,表示此字元不在匹配,下一步需要繼續向右增大滑動視窗。

4.3、不斷收縮左側視窗直到視窗不能完全匹配模式串為止。

5、視窗整個滑動過程模式串 checkmap 不動;

通過乙個變數 curvaildcnt 來記錄表中字元的匹配個數;

curvaildcnt == checkmap.keyset().size() 全匹配收縮左側視窗,直到不匹配;

curvaildcnt < checkmap.keyset().size() 不匹配擴充套件右側視窗,直到匹配

只有在模式串checkmap**現的字元才向滑動視窗slidewinmap表中的新增、刪除;

判斷字元是否相等 == 要將取出的integer型別轉換成intvalue(),因為integer不能隨意使用 == ,其表示的範圍為-128~127。

public string minwindow(string s, string t) 

map check = new hashmap<>();

map window = new hashmap<>();

int curvaildcnt = 0;

for(int i = 0; i < t.length(); i++)

int left = 0,right = 0;

int start = -1,minlen = s.length() + 1;

while(right < s.length())

}while(curvaildcnt == check.keyset().size())

char delch = s.charat(left);

left++;

if(check.containskey(delch))

window.replace(delch,window.get(delch) - 1);}}

} if(start == -1)else

}

給定兩個字串s1s2,寫乙個函式來判斷s2是否包含s1的排列。換句話說,第乙個字串的排列之一是第二個字串的子串。

示例1:

輸入: s1 = "ab" s2 = "eidbaooo"

輸出: true

解釋: s2 包含 s1 的排列之一 ("ba").

示例2:

輸入: s1= "ab" s2 = "eidboaoo"

輸出: false

注意:1、輸入的字串只包含小寫字母;2、兩個字串的長度都在 [1, 10,000] 之間

演算法:1、和leetcode76 完全一致,

2、所不同的是當滑動視窗中 window 的字元和 check 中完全一致且視窗的長度也和待匹配子串長度相等,

即可判定此時的視窗為子串的全排列,返回 true,其它所有場景均為 false

...

while(curvaildcnt == check.keyset().size())

...return false;

}

給定乙個字串 s 和乙個非空字串 p,找到 s 中所有是 p 的字母異位詞的子串,返回這些子串的起始索引。字串只包含小寫英文本母,並且字串 s 和 p 的長度都不超過 20100

說明:

示例 1:

輸入:s: "cbaebabacd" p: "abc"

輸出:[0, 6]

解釋:起始索引等於 0 的子串是 "cba", 它是 "abc" 的字母異位詞。

起始索引等於 6 的子串是 "bac", 它是 "abc" 的字母異位詞。

示例 2:

輸入:s: "abab" p: "ab"

輸出:[0, 1, 2]

解釋:起始索引等於 0 的子串是 "ab", 它是 "ab" 的字母異位詞。

起始索引等於 1 的子串是 "ba", 它是 "ab" 的字母異位詞。

起始索引等於 2 的子串是 "ab", 它是 "ab" 的字母異位詞。

演算法:

1、和leetcode567 完全一致,

2、所不同的是當滑動視窗中 window 的字元和 check 中完全一致且視窗的長度也和待匹配子串長度相等,

即可判定此時的視窗為子串的全排列(字母異位詞),儲存left到list,最後返回list即可。

...

while(curvaildcnt == check.keyset().size())

...return list;

}

給定乙個字串,請你找出其中不含有重複字元的最長子串的長度。

示例 1:

輸入: "abcabcbb"

輸出: 3

解釋: 因為無重複字元的最長子串是 "abc",所以其長度為 3。

示例 2:

輸入: "bbbbb"

輸出: 1

解釋: 因為無重複字元的最長子串是 "b",所以其長度為 1。

示例 3:

輸入: "pwwkew"

輸出: 3

解釋: 因為無重複字元的最長子串是 "wke",所以其長度為 3。

請注意,你的答案必須是 子串 的長度,"pwke" 是乙個子串行,不是子串。

演算法:

1、僅用乙個hashmap用於記錄滑動視窗中的字元,

2、視窗不斷向右新增新字元 ch,當字元ch出現重複時,

2.1、獲取此時視窗長度並更新最大長度,

2.2、從左收縮視窗將重複字元 ch 剔除

3、將新增字元 ch 新增到表中

4、注意長度就算

public int lengthoflongestsubstring(string s) 

window.put(ch,1);

right++;

} return math.max(max,right-left);

}

APT扒了誰的褲子

0 序言 在安全行業渾渾噩噩地浪蕩多年以後,對這個我耐以生存的行業似乎有了一點清晰地認識,而似乎又只是在荒謬中完成又一次的南柯一夢。夢隨心生,心隨境公升,終日流連於摳腳大叔的茫茫滄海,經歷了從人體工學到巧克力鍵盤的時代變遷,我還能做點啥呢!如果說當前安全行業最大的對手是誰,毫無懸念,那就是apt的資...

滑動視窗演算法

我們學習過計算機網路都知道為了避免擁塞發生,在網路傳輸時有滑動視窗協議控制傳輸時流量。該協議允許傳送方在停止並等待確認前傳送多個資料分組。由於傳送方不必每發乙個分組就停下來等待確認,因此該協議可以加速資料的傳輸,提高網路吞吐量。這個跟我們今天說的滑動視窗演算法是乙個原理。該演算法的作用就是將我們多層...

滑動視窗演算法

在letecode程式設計中經常會碰到一類尋找最長序列的問題,這個時候都可以採用滑動視窗的演算法 滑動視窗就是控制乙個雙指標left,right,沒有達到極限條件的時候right指標,操作臨界條件 就讓left指標,然後更新這個最長序列。比如下面的的問題 問題一 給你兩個長度相同的字串,s 和 t。...