滑动窗口学习

1. 解题思路

当出现求连续子串最大/最小,最大/最小子区间之类的题目时,一般采用滑动窗口进行求解。对滑动窗口不了解可以先参考此篇文章

可以按照以下思路进行思考:

  • 1、什么时候应该扩大窗口? 窗口扩大时应该做什么
  • 2、什么时候应该缩小窗口? 窗口缩小时应该做什么
  • 3、什么时候得到一个合法的答案?(求最大是在窗口扩大时更新值,求最小是在窗口缩小时更新值。)

2. 代码

424. 替换后的最长重复字符

class Solution:
    def characterReplacement(self, s: str, k: int) -> int:
        left = 0
        right = 0
        n = len(s)
        s_dict = dict()
        ans = 1
        while (right < n):
            s_dict[s[right]] = s_dict.get(s[right], 0) + 1
            # 除最多字符外,其他字符出现的次数不能超过k次
            while (right - left + 1) - max(s_dict.values()) > k:
                # 先减去最左边的值
                s_dict[s[left]] -= 1
                left += 1
            # 先更新ans
            ans = max(ans, right - left + 1)
            right += 1
        return ans

3. LeetCode其他滑动窗口的题

3. 无重复字符的最长子串
自己写的通过的代码:

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if not s:
            return 0
        left = 0
        right = 0
        n = len(s)
        cur_s = ""
        ans = 1
        while (right < n):
            cur_s += s[right]
            # 这块当时没想通,缩小窗口的条件为出现重复的子串
            while len(cur_s) != len(set(cur_s)):
                cur_s = s[left + 1:right + 1]
                left += 1
            ans = max(ans, right - left + 1)
            right += 1
        return ans

1052. 爱生气的书店老板
此题为固定长度的滑动窗口

class Solution:
    """
    固定大小的滑动窗口
    参考链接:https://leetcode.cn/problems/grumpy-bookstore-owner/solution/hua-dong-chuang-kou-luo-ti-by-ac_oier-nunu/
    思路:先计算本来可以留下的顾客,计算时将本来可以留下的顾客的customers[i]置为0。之后找出在minutes时间内最大的customers子数组和,最后计算答案
    """

    def maxSatisfied(self, customers: List[int], grumpy: List[int], minutes: int) -> int:
        n = len(customers)
        ans = 0
        for i in range(n):
            if grumpy[i] == 0:
                ans += customers[i]
                customers[i] = 0
        minutes_ans = 0
        for i in range(n):
            # i + minutes - 1要取到n-1,但不能大于n-1
            if i + minutes > n:
                break
            minutes_ans = max(minutes_ans, sum(customers[i:i + minutes]))
        return ans + minutes_ans

209. 长度最小的子数组
此题求最小值

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        left = 0
        right = 0
        n = len(nums)
        cur_sum = 0
        ans = n
        while right < n:
            cur_sum += nums[right]
            while cur_sum >= target:
            	# 最小值在窗口缩小时更新
                ans = min(ans, right - left +1)
                cur_sum -= nums[left]
                left += 1
            right += 1
        if target > sum(nums):
            return 0
        return ans

1156. 单字符重复子串的最大长度

1156. 单字符重复子串的最大长度
此题不能直接套用模板,参考官方解答

class Solution:
    def maxRepOpt1(self, text: str) -> int:
        count = collections.Counter(text)
        res = 0
        for i in range(len(text)):
            # step1: 找出当前连续的一段 [i, j)
            j = i
            while j < len(text) and text[j] == text[i]:
                j += 1

            # step2: 如果这一段长度小于该字符出现的总数,并且前面或后面有空位,则使用 cur_cnt + 1 更新答案
            cur_cnt = j - i
            if cur_cnt < count[text[i]] and (j < len(text) or i > 0):
                res = max(res, cur_cnt + 1)

            # step3: 找到这一段后面与之相隔一个不同字符的另一段 [j + 1, k),如果不存在则 k = j + 1
            k = j + 1
            while k < len(text) and text[k] == text[i]:
                k += 1
            res = max(res, min(k - i, count[text[i]]))
            i = j
        return res

4. 参考

  1. https://leetcode.cn/problems/longest-repeating-character-replacement/solution/fen-xiang-zhen-cang-de-shuang-zhi-zhen-m-fdsk/
  2. https://labuladong.github.io/algo/2/20/27/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值