*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

 

posted @ 2019-05-02 11:43  三年一梦  阅读(446)  评论(0编辑  收藏  举报