動機
想起優化LC 127的過程
Problem
Given two strings s
and p
, return an array of all the start indices of p
's anagrams in s
. You may return the answer in any order.
Example 1:
Input: s = cbaebabacd, p = abcOutput: [0,6]Explanation:The substring with start index = 0 is cba, which is an anagram of abc.The substring with start index = 6 is bac, which is an anagram of abc.
Example 2:
Input: s = abab, p = abOutput: [0,1,2]Explanation:The substring with start index = 0 is ab, which is an anagram of ab.The substring with start index = 1 is ba, which is an anagram of ab.The substring with start index = 2 is ab, which is an anagram of ab.
Constraints:
1 <= s.length, p.length <= 3 * 104
s
andp
consist of lowercase English letters.
Sol1
就是sliding windows,但是window裡面連不在pattern中的也一起放進來,導致每次檢查就要先排除不在pattern的字元,這樣會拖慢執行時間
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
ret = []
i = 0
j = len(p)
#print(p)
p = Counter(list(p))
cnt = dict(Counter(s[i:j]))
#print(cnt)
while i < j and j <= len(s):
if all([(k not in p and v == 0) or (k in p and p[k] == v) for (k,v) in cnt.items()]):
ret.append(i)
if j < len(s):
if s[j] not in cnt:
cnt[s[j]] = 1
else:
cnt[s[j]] += 1
j += 1
cnt[s[i]] -= 1
i += 1
#print(i,j,cnt)
return ret
Sol2
在生紀錄window的counter時不把不需要的字元放進去,這樣除了讓執行效率提升,還讓程式變簡單了
這讓我突然想到之前寫BFS(LC 127)是一次把狀態生到需要的狀態,而不是去檢查能不能從起點轉移到下一個狀態,讓效率上升
這裡是不讓不需要的東西進入需要多次檢查的狀態中,這兩個對我來說都有一點類似的感覺
另外關於Counter有兩件事
- Counter有預設值!!
- 可以直接比
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
ret = []
i = 0
j = len(p)
#print(p)
p = Counter(list(p))
cnt = Counter([c for c in s[i:j] if c in p])
while i < j and j <= len(s):
if cnt == p:
ret.append(i)
if j < len(s) and s[j] in p:
cnt[s[j]] += 1
j += 1
if s[i] in p:
cnt[s[i]] -= 1
i += 1
#print(i,j,cnt)
return ret