438. 找到字符串中所有字母异位词

Posted 炫云云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了438. 找到字符串中所有字母异位词相关的知识,希望对你有一定的参考价值。

438. 找到字符串中所有字母异位词

给定两个字符串 sp,找到 s 中所有 p异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指字母相同,但排列不同的字符串。

输入: s = "cbaebabacd", p = "abc"
输出: [0,6]

解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

输入: s = "abab", p = "ab"
输出: [0,1,2]

解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

滑动窗口 + 双指针

用双指针来表示滑动窗口的两侧边界,当滑动窗口的长度等于p的长度时,表示找到一个异位词,

  1. 定义滑动窗口的左右两个指针leftright
  2. right一步一步向右走遍历s字符串
  3. right当前遍历到的字符加入s_count后不满足p_count的字符数量要求,将滑动窗口左侧字符不断弹出,也就是left不断右移,直到符合要求为止。
  4. 当滑动窗口的长度等于p的长度时,这时的s子字符串就是p的异位词。

其中,left和right表示滑动窗口在字符串s中的索引,cur_left和cur_right表示字符串s中索引为left和right的字符在数组s_count中的索引

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        n, m, res = len(s), len(p), []
        if n < m: return res
        p_count = [0] * 26
        s_count = [0] * 26

        for i in range(m):
            p_count[ord(p[i]) - ord('a')] += 1
        
        left = 0
        for right in range(n):
            cur_right = ord(s[right]) - ord('a')
            s_count[cur_right] +=1
            while s_count[cur_right] > p_count[cur_right]:# s_count的字母大于p_count的字符数量要求,收缩窗口
                cur_left = ord(s[left]) - ord('a')
                s_count[cur_left] -=1
                left += 1
            if right - left + 1 == m: #等于p_count的字符数量要求
                res.append(left)
        return res
class Solution:
    def findAnagrams(self, s, p):
        n, m, res = len(s), len(p), []
        if n < m: return res
        p_count = [0] * 26
        s_count = [0] * 26

        for i in range(m):
            s_count[ord(s[i]) - ord('a')] +=1
            p_count[ord(p[i]) - ord('a')] +=1

        left = 0
        for right in range(m,n):
            if p_count == s_count:
                res.append(left)
            # 保持len(p)长度同时移动
            s_count[ord(s[left]) - ord('a')] -=1
            s_count[ord(s[right]) - ord('a')] +=1
            left += 1

        # 避免最后一个窗口没有记录上 所以再进行一次判断
        if p_count == s_count:
            res.append(left)

        return res


class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        # Step 1: 
        # 定义需要维护的变量
        # 本文需要对比两组字符串是否为异位词,所以用哈希表 (abc和bac是异位词是因为他们对应的哈希表相等)
        # 同时我们需要找到所有合法解,所以还需要一个res数组
        
        s_count = {}
        res=[]
        # Step 1.1: 同时把p的哈希表也建立了 (这个哈希表不需要维护,为定值)
        p_count = {}
        for char in p:
            p_count[char] = p_count.get(char,0) +1

        # Step 2: 定义窗口的首尾端 (left, right), 然后滑动窗口
        left = 0
        for right in range(len(s)):
            # Step 3: 更新需要维护的变量 (s_count), 如果 s_count == p_count,代表找到了一个解,加入到res
            s_count[s[right]] = s_count.get(s[right], 0) + 1
            if s_count == p_count:
                res.append(left)
            
            # Step 4 
            # 根据题意可知窗口长度固定,所以用if
            # 窗口左指针前移一个单位保证窗口长度固定, 同时提前更新需要维护的变量 (s_count)

            if right >=len(p) -1:
                s_count[s[left]] -=1
                if s_count[s[left]] ==0:
                    del s_count[s[left]]
                left +=1
        
        # Step 5: 返回答案
        return res

            


参考

Krahets - 力扣(LeetCode) (leetcode-cn.com)

以上是关于438. 找到字符串中所有字母异位词的主要内容,如果未能解决你的问题,请参考以下文章

438. 找到字符串中所有字母异位词

438. 找到字符串中所有字母异位词

438. 找到字符串中所有字母异位词

滑动窗口经典例题之一——438. 找到字符串中所有字母异位词

[LeetCode]438. 找到字符串中所有字母异位词

leetcode中等438找到字符串中所有字母异位词