1. 程式人生 > >438. Find All Anagrams in a String 找到字符串中所有字母異位詞

438. Find All Anagrams in a String 找到字符串中所有字母異位詞

app while pan temp 左移 pen 語句 port code

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

438. Find All Anagrams in a String 找到字符串中所有字母異位詞