438. 找到字符串中所有字母异位词
Posted 炫云云
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了438. 找到字符串中所有字母异位词相关的知识,希望对你有一定的参考价值。
438. 找到字符串中所有字母异位词
给定两个字符串 s
和 p
,找到 s
中所有 p
的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指字母相同,但排列不同的字符串。
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。
滑动窗口 + 双指针
用双指针来表示滑动窗口的两侧边界,当滑动窗口的长度等于p的长度时,表示找到一个异位词,
- 定义滑动窗口的左右两个指针
left
,right
right
一步一步向右走遍历s
字符串right
当前遍历到的字符加入s_count
后不满足p_count
的字符数量要求,将滑动窗口左侧字符不断弹出,也就是left
不断右移,直到符合要求为止。- 当滑动窗口的长度等于p的长度时,这时的
s
子字符串就是p
的异位词。
其中,left和right表示滑动窗口在字符串s中的索引,cur_left和cur_right表示字符串s中索引为left和right的字符在数组s_count中的索引
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
n, m, res = len(s), len(p), []
if n < m: return res
p_count = [0] * 26
s_count = [0] * 26
for i in range(m):
p_count[ord(p[i]) - ord('a')] += 1
left = 0
for right in range(n):
cur_right = ord(s[right]) - ord('a')
s_count[cur_right] +=1
while s_count[cur_right] > p_count[cur_right]:# s_count的字母大于p_count的字符数量要求,收缩窗口
cur_left = ord(s[left]) - ord('a')
s_count[cur_left] -=1
left += 1
if right - left + 1 == m: #等于p_count的字符数量要求
res.append(left)
return res
class Solution:
def findAnagrams(self, s, p):
n, m, res = len(s), len(p), []
if n < m: return res
p_count = [0] * 26
s_count = [0] * 26
for i in range(m):
s_count[ord(s[i]) - ord('a')] +=1
p_count[ord(p[i]) - ord('a')] +=1
left = 0
for right in range(m,n):
if p_count == s_count:
res.append(left)
# 保持len(p)长度同时移动
s_count[ord(s[left]) - ord('a')] -=1
s_count[ord(s[right]) - ord('a')] +=1
left += 1
# 避免最后一个窗口没有记录上 所以再进行一次判断
if p_count == s_count:
res.append(left)
return res
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
# Step 1:
# 定义需要维护的变量
# 本文需要对比两组字符串是否为异位词,所以用哈希表 (abc和bac是异位词是因为他们对应的哈希表相等)
# 同时我们需要找到所有合法解,所以还需要一个res数组
s_count = {}
res=[]
# Step 1.1: 同时把p的哈希表也建立了 (这个哈希表不需要维护,为定值)
p_count = {}
for char in p:
p_count[char] = p_count.get(char,0) +1
# Step 2: 定义窗口的首尾端 (left, right), 然后滑动窗口
left = 0
for right in range(len(s)):
# Step 3: 更新需要维护的变量 (s_count), 如果 s_count == p_count,代表找到了一个解,加入到res
s_count[s[right]] = s_count.get(s[right], 0) + 1
if s_count == p_count:
res.append(left)
# Step 4
# 根据题意可知窗口长度固定,所以用if
# 窗口左指针前移一个单位保证窗口长度固定, 同时提前更新需要维护的变量 (s_count)
if right >=len(p) -1:
s_count[s[left]] -=1
if s_count[s[left]] ==0:
del s_count[s[left]]
left +=1
# Step 5: 返回答案
return res
参考
以上是关于438. 找到字符串中所有字母异位词的主要内容,如果未能解决你的问题,请参考以下文章