题目
输入: s = “cbaebabacd”, p = “abc”
输出: [0,6]
解释:
起始索引等于 0 的子串是 “cba”, 它是 “abc” 的变位词。
起始索引等于 6 的子串是 “bac”, 它是 “abc” 的变位词。
解答
1
- 单独枚举第一个window + 判断
- 用数组来标记代替字典
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
ns = len(p)
nl = len(s)
if ns > nl:
return []
res = []
stat1 = [0] * 26
stat2 = [0] * 26 # reference
for c in p:
stat2[ord(c) - ord('a')] += 1
# first window's stat
for i in range(ns):
stat1[ord(s[i]) - ord('a')] += 1
if stat1 == stat2:
res.append(0)
# from second window on
for i in range(ns, nl):
stat1[ ord(s[i]) - ord('a') ] += 1
stat1[ ord(s[i - ns]) - ord('a') ] -= 1
# print(stat1,stat2,i)
if stat1 == stat2:
res.append(i - ns + 1)
return res
2
- 第一种思路是,从windwow的左边框进行枚举 + hash字典
- 问题在,左边框+window size可能越界,要注意判断。
- 这里使用了defauldict,每次遍历只需要把新窗口左右进行加入和剔除
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
from collections import Counter
from collections import defaultdict
c_s = Counter(p)
res = []
ns = len(p)
nl = len(s)
if ns > nl:
return []
for i in range(nl):
# window = s[i: i+ns]
if i == 0:
print(i)
tmp = defaultdict(int)
for j in range(ns):
tmp[s[j]] += 1
# print(i,window)
else:
tmp[s[i-1]] -= 1
if tmp[s[i-1]] == 0:
del tmp[s[i-1]]
try:
tmp[s[i+ns-1]] += 1
except:
break
# print(i,tmp)
if tmp == c_s:
res.append(i)
return res
3
无脑Counter,复杂度较高
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
from collections import Counter
c_s = Counter(p)
res = []
ns = len(p)
nl = len(s)
if ns > nl:
return []
for i in range(nl):
window = s[i: i+ns]
# print(i,window)
tmp = Counter(window)
if tmp == c_s:
res.append(i)
return res