*438. Find All Anagrams in a String 找到字符串中所有字母异位词
1. 原始题目
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。
字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。
说明:
- 字母异位词指字母相同,但排列不同的字符串。
- 不考虑答案输出的顺序。
示例 1:
输入: s: "cbaebabacd" p: "abc" 输出: [0, 6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词。 起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词。
示例 2:
输入: s: "abab" p: "ab" 输出: [0, 1, 2] 解释: 起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词。 起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词。 起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词。
2. 思路
双指针滑动窗口。[i,j]为左闭又闭区间表示当前的子串。如果下一个位置,即j+1位置的字符在目标串中,且其当前出现次数小于目标串中出现的次数则加入当前串。否则前指针一直向右走。如果j+1位置的字符压根不在目标串中,则将j和i同时更新。
3. 解法
1 from collections import Counter,defaultdict
2 class Solution:
3 def findAnagrams(self, s: str, p: str):
4 c = Counter(p) # 目标串的counter,记录每个元素出现的次数
5 temp = defaultdict(int) # 当前的子串字典
6 i,j=0,-1 # 【i,j】左闭又闭区间表示当前的子串
7 res = [] # 记录结果
8 while(i<len(s) and (j+1)<len(s)):
9
10 if s[j+1] in c: # 如果下一个元素在目标串中
11 if temp[s[j+1]]<c[s[j+1]]: # 如果计数小于目标串的计数
12 temp[s[j+1]] +=1 # 更新子串字典
13 j+=1
14 else:
15 temp[s[i]]-=1 # 否则更新子串字典,左移指针
16 i+=1
17 else: # 如果当前字符压根儿没有出现在目标串中,更新i,j,当前子串
18 j=j+1
19 i=j+1
21 temp = defaultdict(int)
22 if temp==c: # 这条语句一定要放左最后!当前面判断完之后,后面要判断当前子串和目标一样不
23 res.append(i)
24 temp[s[i]]-=1
25 i+=1
26
27 return res