09找到字符串中所有字母异位词
[438.找到字符串中所有字母异位词](438. 找到字符串中所有字母异位词 - 力扣(LeetCode))
思路一:采用滑动窗口法
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
s_len, p_len = len(s), len(p)#分别为s_len,p_len附上长度
if s_len < p_len:#如果字串大于主串则返回空列表
return []
ans = []
s_count = [0] * 26
p_count = [0] * 26
for i in range(p_len):
s_count[ord(s[i]) - 97] += 1#将元素转化为0~25,a的ASCLL值为97
p_count[ord(p[i]) - 97] += 1
if s_count == p_count:
ans.append(0)#上述代码判断s中前len(p)个字符是否是字母异位词
for i in range(s_len - p_len):
s_count[ord(s[i]) - 97] -= 1
s_count[ord(s[i + p_len]) - 97] += 1
#消去上个窗口的起始的字符计数,相当于以窗口大小为len(p)在主串上移动
if s_count == p_count:
ans.append(i + 1)
#若移动窗口后s_count仍等于p_count那么对应的起始索引为当前字符的下一个字符
return ans
作者:力扣官方题解
这段代码是一个名为Solution的类中的一个方法,该方法用于查找字符串s中所有与字符串p为异位词(anagram)的子串的起始索引。异位词是指两个字符串中的字符相同,但顺序不同。
- 首先,获取字符串
s和p的长度,分别存储在变量s_len和p_len中。 - 如果
s的长度小于p的长度,那么不可能存在长度大于s的子串是p的异位词,因此直接返回空列表。 - 初始化一个空列表
ans,用于存储找到的异位词子串的起始索引。 - 创建两个长度为26的列表
s_count和p_count,用于统计字符串s和p中每个字母出现的次数。这里假设输入字符串只包含小写字母。 - 遍历字符串
p,更新p_count列表,统计每个字母出现的次数。 - 遍历字符串
s的前p_len个字符,更新s_count列表,统计每个字母出现的次数。 - 如果此时
s_count和p_count相等,说明找到了一个异位词子串,将起始索引0添加到ans列表中。 - 从第
p_len个字符开始遍历字符串s,每次移动一位,同时更新s_count列表:- 减去当前位置字符的计数
- 加上下一个位置字符的计数
- 每次更新后,检查
s_count和p_count是否相等,如果相等,说明找到了一个异位词子串,将当前位置加1后添加到ans列表中。 - 最后返回
ans列表,包含了所有找到的异位词子串的起始索引。
思路二:取每种结果进行判断(时间复杂度高,时间超了)
class Solution:
def findAnagrams(self, s, p):
list_p=list(p)
list_p.sort()
list_index=[]
for i in range(len(s)):
list_s=list(s[i:i+len(p)])
list_s.sort()
if list_s==list_p:
list_index.append(i)
return list_index

优化的滑动窗口算法
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
s_len, p_len = len(s), len(p)
if s_len < p_len:
return []
ans = []
count = [0] * 26
for i in range(p_len):
count[ord(s[i]) - 97] += 1
count[ord(p[i]) - 97] -= 1
differ = [c != 0 for c in count].count(True)#计算c中初始情况下不为0的个数
if differ == 0:
ans.append(0)#差异为0
for i in range(s_len - p_len):
if count[ord(s[i]) - 97] == 1:
differ -= 1
# 说明s[i]不是p中的字符,那么窗口移动则需先消除s[i]对differ的影响
elif count[ord(s[i]) - 97] == 0:
differ += 1
# 说明s[i]是p中的字符,那么窗口移动则需先消除s[i]对differ的影响
count[ord(s[i]) - 97] -= 1#去除这个字符对列表count影响
if count[ord(s[i + p_len]) - 97] == -1:
differ -= 1
# 说明s[i + p_len]在p中,differ-1
elif count[ord(s[i + p_len]) - 97] == 0:
differ += 1
# 说明s[i + p_len]可能与之前的字符重复,或者不在p中
count[ord(s[i + p_len]) - 97] += 1#代表s[i + p_len]已经在窗口中
if differ == 0:
ans.append(i + 1)
return ans
作者:力扣官方题解
这段代码是一个名为 Solution 的类中的一个方法,该方法用于寻找字符串 s 中所有与字符串 p 为异位词(anagram)的子串的起始索引。异位词是指两个字符串中的字符相同,但顺序不同。
代码的主要逻辑如下:
-
首先检查输入字符串
s的长度是否小于字符串p的长度,如果是,则直接返回空列表,因为无法在较短的字符串中找到长度大于它的异位词。 -
初始化一个长度为 26 的计数数组
count,用于统计每个字母在字符串p中出现的次数。同时,将字符串s的前p_len个字符对应的计数减一,以便于后续计算窗口内字母的数量差异。 -
计算初始窗口内字母数量的差异
differ,即count数组中非零元素的数量。如果differ为零,说明当前窗口内的字母分布与字符串p相同,因此将起始索引 0 添加到结果列表ans中。 -
遍历字符串
s,每次移动窗口一位,并更新计数数组count以及字母数量差异differ。具体来说,对于窗口左侧即将离开的字符s[i],如果其计数从负数变为正数或从正数变为零,说明该字符的数量差异发生了变化,需要相应地更新differ。对于窗口右侧新加入的字符s[i + p_len],同样进行类似的操作。 -
当窗口内字母数量差异
differ为零时,说明当前窗口内的字母分布与字符串p相同,因此将当前窗口的起始索引i + 1添加到结果列表ans中。 -
最后返回结果列表
ans,包含了所有满足条件的子串的起始索引。
遍历方法求解以及对leetcode官方题解的解释
浙公网安备 33010602011771号