1. 程式人生 > 實用技巧 >LeetCode-567-字串的排列-滑動視窗

LeetCode-567-字串的排列-滑動視窗

567、字串的排列

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

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

示例1:

輸入: s1 = "ab" s2 = "eidbaooo"
輸出: True
解釋: s2 包含 s1 的排列之一 ("ba").

示例2:

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

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/permutation-in-string

解題思路: 左右設定兩個下標,左右下標圍成一小塊區域為視窗,在要匹配的字串上進行從前往後的滑動,找到符合題意的子串 視窗初始化:左右下標初始為0 步驟:右下標一個一個往後移動,每當找到一個目標字元,就加入視窗中,直到視窗中包含所有要找的字元,當滿足條件時,才移動左下標,來優化結果,縮小視窗,移動時要判斷左下標右移後要刪掉的那個元素是否是題目所需,如果是還要進行一系列操作,詳細參見程式碼中的註釋。
class
Solution(object): def checkInclusion(self, s1, s2): windows = dict() needs = dict() for i in s1: if i in needs: needs[i] = needs[i] + 1 else: needs[i] = 1 right = left = 0 voiad = 0 while
right < len(s2):#右下標不能超過字串末尾 c = s2[right]#提取右下標指向的元素c right += 1#右下標右移一位 if c in needs:#如果c是需要的字元,則對字元進行操作,如果不是,直接下次迴圈,直到右下標指向有用的字元 if c in windows:#如果c曾找到過,曾放入過視窗中,則直接數量加1 windows[c] = windows[c] + 1 else:#
如果c不曾找到過,視窗中還未曾加入過,則置視窗中該字元的數量為1,說明此刻找到了一個 windows[c] = 1 if windows[c] == needs[c]:#如果c這個字元的數量,和要求的c的數量相同,則說明c這個字元找夠了,則將已找到的字母數+1 voiad += 1 while voiad == len(needs):#已找到的的字母數=要找的字符集的字母數,說明視窗中已經包含了所有要找的字母了(包括每個字母的不同個數),可以進行視窗的優化了 d = s2[left]#記下左下標所指的字元d left = left + 1#左下標右移一位 if right - left + 1 == len(s1):#如果視窗長度和要求的s1長度相同,說明不包含冗餘字元,符合要求,輸出true return True if d in needs:#視窗長度和要求的s1長度不同,要進行滑窗,如果即將剔除的字元d是目標字元之一 if windows[d] == needs[d]:#如果視窗中的d字元是找夠了的,但剔除後,這個字元就少了一個,就不是數量找夠的字元了,那麼將已找夠的字母數-1 voiad -= 1 windows[d] = windows[d] - 1#視窗中的d也-1 return False