參考文章:leetcode438題解答
0x00:前言
leetcode上有好幾道個子字符串有關的題目,兩天前看到一題要求找到字符串中所有字母異位詞,題目大致意思是有s和p兩個字符串,找出s中和p字母相同但順序可以不相同的子字符串,並返回這些子串的起始索引。
例子:
輸入:
s: "cbaebabacd" p: "abc"
輸出:
[0, 6]
解釋:
起始索引等於 0 的子串是 "cba", 它是 "abc" 的字母異位詞。
起始索引等於 6 的子串是 "bac", 它是 "abc" 的字母異位詞。
題目鏈接:https://leetcode-cn.com/probl...
0x01:算法思路
想象一塊在窗口上滑動的玻璃窗,它的“左”邊和“右”邊都是可以移動的,也就是這個玻璃窗的位置可以移動,寬度也可以變化。這麼一說好像更像窗簾……
思路如下:
- 建立雙指針,初始化left與right兩個指針,以
[left, right]
這個閉區間做爲窗口 - 首先拉動這個窗口的右邊,窗口不斷擴大,直到窗口中內容符合要求
- 現在移動窗口的左邊,直到窗口中內容不符合要求
- 重複2、3步驟,直到窗口右邊達到邊界
使用這種方式,可以方便的解決子字符串相關問題。
0x02:具體解決
- 首先在代碼中,雙指針
right
和left
不能少,同時還需要一個值來記錄匹配情況 - 返回值需要一個列表,來記錄匹配的子字符串首位索引
- 使用hash表來記錄字符串p中各個字符數量,在Python中使用
Count
類,它是字典dict
的子類,可以使用字典常用的方法 - 移動
right
來遍歷字符串s,如果right
所在的字符存在於t中,將其存入window這個字典中,並將記錄其數量的值加一。
window[key] = window.get(key, 0) + 1
# 字典的get方法:dict.get(key, default=None),返回字典中key的值,如果key不存在,就返回默認的default值。
# 這樣寫保證window[key]值增加1,如果不存在這個鍵就會創建
- 當
window
中記錄字符的數量與needs
中相等時,表示我們匹配完了一個字符,將match
值加一 - 等到匹配的字符長度合適了,就可以將left的值
append
到需要返回的列表中去了
while match == len(needs):
if right - left == len(p):
res.append(left)
- 移動
left
,直到窗口內容不再符合我們需要的異序字符串,將match
值也減一
完整代碼如下:
from collections import Counter
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
res = []
right, left, match = 0, 0, 0
needs = Counter(p)
window = {}
while right < len(s):
key1 = s[right]
if key1 in needs:
window[key1] = window.get(key1, 0) + 1
if window[key1] == needs[key1]:
match += 1
right += 1
while match == len(needs):
if right - left == len(p):
res.append(left)
key2 = s[left]
if key2 in needs:
window[key2] = window[key2] - 1
if window[key2] < needs[key2]:
match -= 1
left += 1
return res
掃描二維碼關注公衆號查看更多文章: