Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.
Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.
The order of output does not matter.
Example 1:
Input: s: "cbaebabacd" p: "abc" Output: [0, 6] Explanation: The substring with start index = 0 is "cba", which is an anagram of "abc". The substring with start index = 6 is "bac", which is an anagram of "abc".
Example 2:
Input: s: "abab" p: "ab" Output: [0, 1, 2] Explanation: The substring with start index = 0 is "ab", which is an anagram of "ab". The substring with start index = 1 is "ba", which is an anagram of "ab". The substring with start index = 2 is "ab", which is an anagram of "ab".
LeetCode:链接
给出两个字符串,要找出所有的s包含的p的所有的同字母异自序的所有词的起始下标。正如上面的例子所示的,很显然,需要满足这几个要求:第一个就是s的子串的长度和p的长度是一样的;第二个是,组成的字符种类相同,并且每个种类的个数也相同。说到这里,基本可以看出这个题目的要点是Hash表和滑动窗口。
1)首先统计字符串p的字符个数,然后用两个变量left和right表示滑动窗口的左右边界,用变量count表示字符串p中需要匹配的字符个数,然后开始循环。
2)如果右边界的字符已经在哈希表中了,说明该字符在p中有出现,则count自减1,然后哈希表中该字符个数自减1,右边界自加1,如果此时count减为0了,说明p中的字符都匹配上了,那么将此时左边界加入结果res中。
3)如果此时right和left的差为p的长度,说明此时应该去掉最左边的一个字符,我们看如果该字符在哈希表中的个数大于等于0,说明该字符是p中的字符,为啥呢,因为上面我们有让每个字符自减1,如果不是p中的字符,那么在哈希表中个数应该为0,自减1后就为-1,所以这样就知道该字符是否属于p,如果我们去掉了属于p的一个字符,count自增1。
class Solution(object):
def findAnagrams(self, s, p):
"""
:type s: str
:type p: str
:rtype: List[int]
"""
left = right = 0
count = len(p)
# 确定p的hash table
p_dict = {}
for i in p:
p_dict[i] = p_dict.get(i, 0) + 1
res = []
while right < len(s):
if s[right] in p_dict:
# 只有p的hash table的元素存在 才能在count中减去
if p_dict[s[right]] >= 1:
count -= 1
p_dict[s[right]] -= 1
right += 1
if count == 0:
res.append(left)
if right - left == len(p):
if s[left] in p_dict:
# 只有p的hash table的元素大于等于0 不为负数 说明之前在count中减去了
if p_dict[s[left]] >= 0:
count += 1
p_dict[s[left]] += 1
left += 1
return res