滑动窗口

滑动窗口

滑动窗口实际上也是双指针的应用,滑动窗口的右指针不断扩大窗口的范围,当窗口内的对象符合某个条件时,进行统计或者某种操作;然后左指针收缩窗口来打破条件,以便让右指针右移继续扩大窗口

滑动窗口题目:

3. 无重复字符的最长子串(使用左右指针构造一个滑动窗口,确保滑动窗口内的子串满足要求)

30. 串联所有单词的子串

76. 最小覆盖子串

159. 至多包含两个不同字符的最长子串

209. 长度最小的子数组

239. 滑动窗口最大值

567. 字符串的排列

632. 最小区间

727. 最小窗口子序列

3. 无重复字符的最长子串

解题思路:定义一个数组作为滑动窗口,如果一个字符不在窗口内,则加入;反之,从左边开始删除滑动窗口内的字符来调整窗口;

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if not s:
            return 0 
        i = 0
        windowArr = []
        max_len = 0
        while i<len(s):
            if s[i] not in windowArr:
                windowArr.append(s[i])
                i+=1
                max_len = max(max_len, len(windowArr))
            else:
                while s[i] in windowArr:
                    windowArr.pop(0)           
        return max_len 

76. 最小覆盖子集

思路:使用一个字典来统计滑动窗口内每个字符以及出现的次数,
如果窗口内字符以及出现的次数跟目标字符串一致时,则统计窗口内字符的长度,然后将左指针往前移动来缩减窗口,直到窗口内匹配的字符个数少于目标字符串时;
如果匹配的个数少于目标字符串时,不断右指针往前移动,来扩大窗口的范围;
当右指针直到s字符串的最后一个字符时,算法结束

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        if not t or not s:
            return ""
        dic = collections.Counter(t)
        required = len(dic)
        l, r = 0, 0
        formed = 0
        windowCounts = {}
        ans = float("inf"), None, None
        while r < len(s):
            character = s[r]
            windowCounts[character] = windowCounts.get(character, 0) + 1
            if character in dic and windowCounts[character] == dic[character]:
                formed += 1
            while l <= r and formed == required:
                character = s[l]
                if r - l + 1 < ans[0]:
                    ans = (r - l + 1, l, r)
                windowCounts[character] -= 1
                if character in dic and windowCounts[character] < dic[character]:
                    formed -= 1
                l += 1
            r += 1    
        return "" if ans[0] == float("inf") else s[ans[1] : ans[2] + 1]

159:至多包含两个不同字符的最长子串

思路:
用左右指针来构建一个滑动窗口,
当窗口内的不同字符个数<=2时,右指针右移来扩大窗口,并统计窗口的长度;
当窗口内不同字符的个数>2时,左指针右移来缩小窗口

class Solution:
    def lengthOfLongestSubstringTwoDistinct(self, s: str) -> int:
        if len(s)<3:
            return len(s)
        i, j = 0, 0 
        max_len = 0
        while j<len(s):
            if len(set(s[i:j+1]))<=2:                
                max_len = max(max_len, j-i+1)
                j+=1
            else:
                while i<=j and len(set(s[i:j+1]))>2:
                    i+=1
        return max_len

209 长度最小的子数组

使用左右指针来构建一个滑动窗,
当窗口内的数字的和<s时,右指针右移来扩大窗口;
当窗口内的数字之和>=s时,统计窗口的长度,并将左指针右移来缩小窗口

class Solution:
    def minSubArrayLen(self, s: int, nums: List[int]) -> int:
        if not nums:
            return 0 
        i, j = 0, 0 
        windowSum = 0
        min_len = float('inf')
        while j<len(nums):       
            windowSum += nums[j]
            while i<=j and windowSum>=s:
                min_len = min(min_len, j-i+1)
                windowSum -= nums[i]
                i+=1
            j+=1

        return 0 if min_len == float('inf') else min_len
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值