📜  数据结构 |队列 |问题 11(1)

📅  最后修改于: 2023-12-03 15:40:00.668000             🧑  作者: Mango

数据结构 | 队列 | 问题 11

问题描述

给定一个由小写字母组成的字符串 s 和一个非空字符串 p,搜索 s 中所有是 p 的排列的子串,返回这些子串的起始索引。字符串只包含小写英文字母,并且字符串 sp 的长度都不超过 20,100。

排列指字母的相对位置可以改变。例如,字符串 abc 的排列是 abcacbbacbcacabcba

问题分析

这是一个经典问题,可以使用队列来解决。首先,我们将字符串 p 中的字符以及它们出现的次数记录下来,然后用队列来维护一个长度为 p 的滑动窗口,在每个位置上,我们将字符加入队列中,并检查队列是否匹配 p 中的字符及其出现次数。如果队列匹配,我们就把当前位置加入结果数组中。

具体地,我们使用两个哈希表 needwindow 来维护滑动窗口中字符出现的次数。其中,need 记录 p 中每个字符出现的次数,window 记录当前滑动窗口中每个字符出现的次数。我们还需要一个变量 valid 来表示当前滑动窗口中已经匹配 p 中字符的个数。在移动滑动窗口时,我们需要更新窗口中字符出现的次数以及更新 valid 的值,如果当前队列满足条件,则将左端点加入结果数组中。

代码实现
def findAnagrams(s: str, p: str) -> List[int]:
    n = len(s)
    m = len(p)
    if n < m:
        return []
    
    ans = []
    need = {}
    window = {}
    for c in p:
        if c not in need:
            need[c] = 0
        need[c] += 1
    
    left = 0
    right = 0
    valid = 0
    while right < n:
        c = s[right]
        right += 1
        if c in need:
            if c not in window:
                window[c] = 0
            window[c] += 1
            if window[c] == need[c]:
                valid += 1
        
        while right - left >= m:
            if valid == len(need):
                ans.append(left)
            
            d = s[left]
            left += 1
            if d in need:
                if window[d] == need[d]:
                    valid -= 1
                window[d] -= 1
    
    return ans
总结

队列是一种非常有用的数据结构,在解决一些滑动窗口问题时,特别有效。在这个问题中,我们学习了如何使用队列来判断字符串 s 中是否存在由字符串 p 的字符排列组成的子串,并且还学习了如何使用哈希表来维护字符出现的次数。这是一个非常好的问题,值得深入掌握。