题目描述:
解题思路一:
利用
need
来保存需要目标子串的所有字符出现次数
利用
have
来保存当前窗口下的子串的所有字符出现次数
match
表示满足字符出现次数的数量
plen
表示需要满足字符出现次数的数量
1.
移动
right
指针,当
have[s[right]]==need[s[right]]
时,
match++
2.
当
match==plen
且窗口大小等于所需字符数量,保存结果
3.
当
match==plen
且窗口大小大于所需字符数量,移动
left
指针,并令对应的
have[s[left]]--
,如果
have[s[left]] < need[s[left]]
,令
match--
4.
重复
123
步直到
right
指针到最右边
解决代码:
class Solution(object):
def findAnagrams(self, s, p):
"""
:type s: str
:type p: str
:rtype: List[int]
"""
# 滑动窗口解决此类问题
left, right, match = 0, 0, 0 #初始化窗口的左右指针,以及判断窗口内字母是否与p匹配,其中match表示的是窗口中某字母出现的次数与p中该字母出现的次数(是否相同)相同的次数。
need, have = {}, {} #初始化两个字典,保存需要的p的字母数量以及窗口内有的字符数量
for x in p:
need[x] = need.get(x, 0) + 1 #对p中的字母数量进行初始化
pset = set(p) #利用set函数得到p中不重复的字母list
plen = len(pset) #得到p中不重复的字母个数
window = len(p) #窗口大小即为p的所有字母个数
result = [] #用来保存结果的list
while right < len(s): #进入循环
#先移动 right
if s[right] in pset:
have[s[right]] = have.get(s[right], 0) + 1 #对have中的字母计数
if have[s[right]] == need[s[right]]:
match += 1
#再移动left
while match == plen: #当匹配的次数与plen相同时
if right - left == window:
result.append(left) #找到起始位置
if s[left] in pset: #判断左字母是否重复
have[s[left]] = have.get(have[left], 0) - 1
if have[s[lsft]] < need[s[left]]:#判断是否需要修改match
match -= 1
left += 1
return result
提交结果:超时
解题思路二:
构建哈希数组,以0~25,分别代表26个字母,并且计数每个字母出现的次数,再用滑动窗口的方法进行寻找。
解决代码如下:
class Solution(object):
def findAnagrams(self, s, p):
"""
:type s: str
:type p: str
:rtype: List[int]
"""
# 滑动窗口模板解决此类问题
# ord("a") = 97
sArr = [ord(i)-97 for i in s]
pArr = [ord(i)-97 for i in p]
hash = [0 for i in range(26)]
m,n = len(s),len(p)
# 构建hash映射数组
for i in range(n):
hash[pArr[i]] += 1
l,r,count,res= 0,0,0,[]
while r < m:
hash[sArr[r]] -= 1
if hash[sArr[r]] >= 0:
count += 1
# 移动左指针
if r > n - 1:
hash[sArr[l]] += 1
if hash[sArr[l]] > 0:
count -= 1
l += 1
if count == n:
res.append(l)
r += 1
return res
提交结果: