438. Find All Anagrams In A String



438. Find All Anagrams In A String (Medium) 找到字符串中所有字母的异位词

题干

Given two strings s and p, return an array of all the start indices of p’s anagrams in s. You may return the answer in any order.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

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".

Constraints:

解法

朴素解法

这个解法算是暴力解法了

划动窗口解法

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        ans: List[int] = []
        n: int = len(s)
        m: int = len(p)
        if n < m:
            return ans
        
        sw_s: Dict[str, int] = defaultdict(int)
        sw_p: Dict[str, int] = defaultdict(int)
        for i in range(m):
            sw_p[p[i]] += 1
            sw_s[s[i]] += 1
        # 校验第一个窗口
        if sw_s == sw_p:
            ans.append(0)
        
        for j in range(m,n):
            # 先划动,再记录,保证记录所有可能
            sw_s[s[j-m]] -= 1
            sw_s[s[j]] += 1
            if sw_s[s[j-m]] == 0:
                sw_s.pop(s[j-m])
            if sw_s == sw_p:
                ans.append(j-m+1)
        return ans

无dict写法:因为都是小写字母,本身就是有顺序的,所以可以使用list代替dict(算法无改变,只是数据结构变了

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        ans: List[int] = []
        n: int = len(s)
        m: int = len(p)
        if n < m:
            return ans
        
        # 26个英文字母,26个slot,下标就代表字母顺序
        sw_s: List[int] = [ 0 for x in range(26) ]
        sw_p: List[int] = [ 0 for x in range(26) ]

        # 构建窗口,逐个元素求和字符a的ascii码差值(正好等于上面数据结构下标)
        for i in range(m):
            sw_p[ord(p[i])-ord("a")] += 1
            sw_s[ord(s[i])-ord("a")] += 1
        # 校验第一个窗口
        if sw_s == sw_p:
            ans.append(0)
        
        for j in range(m,n):
            # 先划动,再记录,保证记录所有可能
            sw_s[ord(s[j-m])-ord("a")] -= 1
            sw_s[ord(s[j])-ord("a")] += 1
            if sw_s == sw_p:
                ans.append(j-m+1)
        return ans