567 字串的排列

2021-10-19 08:37:54 字數 1658 閱讀 2264

給定兩個字串 s1 和 s2,寫乙個函式來判斷 s2 是否包含 s1 的排列。

換句話說,第乙個字串的排列之一是第二個字串的子串。

示例1:

輸入: s1 = 「ab」 s2 = 「eidbaooo」

輸出: true

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

示例2:

輸入: s1= 「ab」 s2 = 「eidboaoo」

輸出: false

注意:輸入的字串只包含小寫字母

兩個字串的長度都在 [1, 10,000] 之間

解題思路:

滑動視窗 + 字典

定義乙個長度與s1相同的滑動視窗,可以是陣列也可以是字典。本人用的是字典,滑動視窗放在s2上,left為s2的最左端點開始向右步長為1開始滑動,定義 counter1 是對 s1 內字元出現的個數的統計,定義 counter2 是對 s2 內字元出現的個數的統計。在視窗每次右移的時候,需要把右邊新加入視窗的字元個數在 counter2 中加 1,把左邊移出視窗的字元的個數減 1。如果 counter1 == counter2 ,那麼說明視窗內的子串是 s1 的乙個排列,返回 true;如果視窗已經把 s2 遍歷完了仍然沒有找到滿足條件的排列,返回 false。

class

solution

:def

checkinclusion

(self, s1:

str, s2:

str)

->

bool

:# 統計 s1 中每個字元出現的次數

n=len(s2)

# 定義滑動視窗的範圍是 [left, right],閉區間,長度與s1相等

left=

0 right=

len(s1)-1

# 統計視窗s1內的元素出現的次數

counter1 = collections.counter(s1)

# 統計視窗s2[left, right - 1]內的元素出現的次數

counter2 = collections.counter(s2[

0:right]

)while rightcounter2[s2[right]]+=

1if counter1==counter2:

return

true

counter2[s2[left]]-=

1# 如果當前 left 位置的元素出現次數為 0, 需要從字典中刪除,否則這個出現次數為 0 的元素會影響兩 counter 之間的比較

if counter2[s2[left]]==

0:del counter2[s2[left]

] left+=

1 right+=

1return

false

本題中的 counter 可以用字典,也可以用陣列來實現。用字典的時候,需要注意:如果移除 left 元素後,若 counter2[s2[left]] == 0 那麼需要從字典中刪除 left 這個key。因為 和 是不等的。

counter2 初始化的時候只放了 [0, right - 1] 個元素,因為在 while 迴圈中的第一行就是把 right 元素放到 counter2 中。

567 字串的排列

給定兩個字串 s1 和 s2,寫乙個函式來判斷 s2 是否包含 s1 的排列。換句話說,第乙個字串的排列之一是第二個字串的子串。示例1 輸入 s1 ab s2 eidbaooo 輸出 true 解釋 s2 包含 s1 的排列之一 ba 思路 注釋 public boolean checkinclus...

567 字串的排列

題意理解 查詢乙個字串中的子串是否是另乙個字元的排列 問題分析 陣列滑動視窗 map 將待匹配的字串轉化成字典來比較,每次滑動字串,只需要修改字典中首尾字元的數量即可。對於數量為0的字元,需要從map中刪除。如果不刪除,無法直接用字典相等來判斷。其他做了40分鐘,慢了。一遍準。鏈結bool chec...

567 字串的排列

給定兩個字串s1和s2,寫乙個函式來判斷s2是否包含s1的排列。換句話說,第乙個字串的排列之一是第二個字串的子串。示例1 輸入 s1 ab s2 eidbaooo 輸出 true解釋 s2 包含 s1 的排列之一 ba 示例2 輸入 s1 ab s2 eidboaoo 輸出 false注意 輸入的字...