滑动窗口的应用 python

滑动窗口的应用

2022.09.18
滑动窗口可用于解决一些列的字符匹配问题,典型的问题包括:在字符串 s s s 中找到一个最短的子串,使得其能覆盖到目标字符串 t t t。对于目标字符串 t t t,我们可以在字符串 s s s 上滑动窗口,当窗口包含 t t t 中的全部字符后,我们再根据题意考虑能否收缩窗口。
先把参考链接放上来
『 一招吃遍七道 』滑动窗口的应用

作者:flix
链接:https://leetcode.cn/problems/minimum-window-substring/solution/by-flix-1kac/

思路写的太好了,困扰好久的滑动窗口解决了。

变长滑动窗口:字符串

1.76. 最小覆盖子串
2.剑指 Offer II 017. 含有所有字符的最短字符串

class Solution:
    def minWindow(self, s, t):
        if len(t) > len(s):
            return ''        
        cnt = collections.Counter(t)    # 哈希表:记录需要匹配到的各个元素的数目
        need = len(t)                   # 记录需要匹配到的字符总数【need=0表示匹配到了】
        n = len(s)
        start, end = 0, -1          # 记录目标子串s[start, end]的起始和结尾
        min_len = n + 1             # 符合题意的最短子串长度【初始化为一个不可能的较大值】
        left = right = 0            # 滑动窗口的左右边界
        for right in range(n):
            # 窗口右边界右移一位
            ch = s[right]               # 窗口中新加入的字符
            if ch in cnt:               # 新加入的字符位于t中
                if cnt[ch] > 0:         # 对当前字符ch还有需求
                    need -= 1           # 此时新加入窗口中的ch对need有影响
                cnt[ch] -= 1
            # 窗口左边界持续右移
            while need == 0:            # need=0,当前窗口完全覆盖了t
                if right - left + 1 < min_len:      # 出现了更短的子串
                    min_len = right - left + 1
                    start, end = left, right
                ch = s[left]            # 窗口中要滑出的字符
                if ch in cnt:           # 刚滑出的字符位于t中
                    if cnt[ch] >= 0:    # 对当前字符ch还有需求,或刚好无需求(其实此时只有=0的情况)
                        need += 1       # 此时滑出窗口的ch会对need有影响
                    cnt[ch] += 1
                left += 1               # 窗口左边界+1 
        return s[start: end+1]

变长滑动窗口:数组

  1. 面试题 17.18. 最短超串
class Solution:
    def shortestSeq(self, big, small):
        if len(small) > len(big):
            return []     
        cnt = collections.Counter(small)    # 哈希表:记录需要匹配到的各个元素的数目
        need = len(small)                   # 记录需要匹配到的元素总数【need=0表示匹配到了】
        n = len(big)
        res = []                    # 记录目标子数组的起始和结尾
        min_len = n + 1             # 符合题意的最短字数组长度【初始化为一个不可能的较大值】
        left = right = 0            # 滑动窗口的左右边界
        for right in range(n):
            # 窗口右边界右移一位
            num = big[right]            # 窗口中新加入的元素
            if num in cnt:              # 新加入的元素位于small中
                if cnt[num] > 0:        # 对当前元素num还有需求
                    need -= 1           # 此时新加入窗口中的元素num对need有影响
                cnt[num] -= 1  
            # 窗口左边界持续右移
            while need == 0:            # need=0,当前窗口完全覆盖了small
                if right - left + 1 < min_len:      # 出现了更短的子数组
                    min_len = right - left + 1
                    res = [left, right]    
                num = big[left]         # 窗口中要滑出的元素
                if num in cnt:          # 刚滑出的元素位于small中
                    if cnt[num] >= 0:   # 对当前元素num还有需求,或刚好无需求(其实此时只有=0的情况)
                        need += 1       # 此时滑出窗口的元素num会对need有影响
                    cnt[num] += 1
                left += 1               # 窗口左边界+1
        return res

定长滑动窗口:异位词
4. 567. 字符串的排列
5. 剑指 Offer II 014. 字符串中的变位词

class Solution:
    def checkInclusion(self, s1, s2):
        m, n = len(s1), len(s2)
        if m > n:
            return False
        cnt = collections.Counter(s1)   # 哈希表:记录需要匹配到的各个字符的数目
        need = m                        # 记录需要匹配到的字符总数【need=0表示匹配到了】
        for right in range(n):
            # 窗口右边界
            ch = s2[right]              # 窗口中新加入的字符
            if ch in cnt:               # 新加入的字符ch位于s1中
                if cnt[ch] > 0:         # 此时新加入窗口中的字符ch对need有影响
                    need -= 1
                cnt[ch] -= 1
            # 窗口左边界
            left = right - m
            if left >= 0:
                ch = s2[left]
                if ch in cnt:           # 刚滑出的字符位于s1中
                    if cnt[ch] >= 0:    # 此时滑出窗口的字符ch对need有影响
                        need += 1
                    cnt[ch] += 1
            if need == 0:               # 找到了一个满足题意的窗口
                return True
        return False

定长滑动窗口:异位词的位置
6. 438. 找到字符串中所有字母异位词
7. 剑指 Offer II 015. 字符串中的所有变位词

class Solution:
    def findAnagrams(self, s, p):
        n, m = len(s), len(p)
        if m > n:
            return []
        cnt = collections.Counter(p)    # 哈希表:记录需要匹配到的各个字符的数目
        need = m                        # 记录需要匹配到的字符总数【need=0表示匹配到了】
        res = []
        for right in range(n):
            # 窗口右边界
            ch = s[right]               # 窗口中新加入的字符
            if ch in cnt:               # 新加入的字符位于p中
                if cnt[ch] > 0:         # 此时新加入窗口中的字符对need有影响
                    need -= 1
                cnt[ch] -= 1
            # 窗口左边界
            left = right - m
            if left >= 0:
                ch = s[left]
                if ch in cnt:           # 刚滑出的字符位于p中
                    if cnt[ch] >= 0:    # 此时滑出窗口的字符对need有影响
                        need += 1
                    cnt[ch] += 1
            if need == 0:           # 找到了一个满足题意的窗口,其左端点为right-m+1
                res.append(right - m +1)
        return res

你可能感兴趣的:(每日一道leetcode,python,leetcode,开发语言)