[Leetcode解題] 438. Find All Anagrams in a String
6 January 2024
medium
two-pointers
hashmap
題目
438. Find All Anagrams in a String
給定兩個字串s1
與s2
,判斷s2
中是否包含s1
其中一種排列組合的子字串,回傳各個位置的indices
解題思路
跟567. Permutation in String很類似,我們也是透過搜尋set
的概念來解。
這邊我們用兩個指標分別為head
跟tail
來代表起始跟結束,兩指標之間的子字串(substring)即為我們正在判斷的anagram
我們一開始先將目標字串建立成hashmap
或字典
的形式,舉例來說abc
就會建立成{a: 1, b: 1, c: 1}
的形式。
接下來,我們開始在字串s
中搜尋,每當tail
往前一步,就會減少hashmap
對應字元的數目,反之,head
往前一步就會增加,只要hashmap
中所有字元的數目皆為零即表示我們找到一組解答。
但是,有下列兩種情況需要特別考慮:
- 如果tail指到的字元不存在於字典中:那麼包含這個位置一定不可能構成跟目標一樣的
set
,所以我們要把tail
跟head
都移動到下一個字元的位置 - 如果字典中該字元的數量已經為0:那麼我們需要移動head來將一些字元加回去讓其有機會繼續往前移動。
最後,我們其實不需要判斷說字典每個值都為零,我們只需要確認tail
跟head
之間的字串長度是否跟p
一樣即可,因為tail
和head
的距離就是我們從字典拿走多少數目。
實作
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
d = {}
for c in p:
d.setdefault(c, 0)
d[c] += 1
output = []
head = 0
tail = 0
while tail < len(s):
if s[tail] not in d:
while head < tail:
d[s[head]] += 1
head += 1
head = tail = tail + 1
elif d[s[tail]] == 0:
d[s[head]] += 1
head += 1
else:
d[s[tail]] -= 1
tail += 1
if tail - head == len(p):
output.append(head)
d[s[head]] += 1
head += 1
return output
時間複雜度
因為使用兩個指標跑過一次迴圈所以為$O(n)$