滑动窗口题集 - 序列一

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

问题描述

  • 给定一个字符串,寻找该字符串中不包含重复字符的最长子串的长度。

算法步骤

  1. 初始化两个指针leftright 分别表示窗口的左右边界。
  2. 扩展右边界:向右移动 right 指针以扩展窗口,直到窗口包含重复字符。
  3. 收缩左边界:一旦发现重复字符,向右移动 left 指针以缩小窗口,直到窗口不再包含重复字符。
  4. 更新结果:在每一步中,更新不含重复字符的最长子串的长度。
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        ans = 0
        left = 0
        cnt = defaultdict(int)  # 维护从下标 left 到下标 right 的字符

        for right, x in enumerate(s):
            cnt[x] += 1
            while left <= right and cnt[x] >= 2:
                cnt[s[left]] -= 1
                left += 1 # 缩小窗口
            ans = max(ans, right - left + 1) # 更新窗口长度最大值
        
        return ans

LeetCode-2024. 考试的最大困扰度

题意

  • 求给定字符串 answerKey 的一个最长子串,该子串至多包含 kT 或者至多包含 kF

算法步骤

  1. 初始化:定义两个指针 leftright,分别表示子串的左右端点。定义一个计数器 cnt 用于记录子串中 TF 的数量。

  2. 扩展右端点

    • 遍历 answerKey,逐渐增加 right 指针。
    • answerKey[right] 的出现次数加一。
  3. 调整左端点

    • 如果 TF 的出现次数都超过 k,则不断移动左端点 left,同时减少 answerKey[left] 的出现次数,直到 TF 的出现次数至少有一个小于或等于 k
  4. 更新结果

    • 每次循环结束后,用子串长度 right - left + 1 更新答案的最大值。
  5. 返回答案

    • 遍历结束后,返回记录的最长有效子串长度。
class Solution:
    def maxConsecutiveAnswers(self, answerKey: str, k: int) -> int:
        ans = left = 0
        cnt = defaultdict(int)

        for right, ch in enumerate(answerKey):
            cnt[ch] += 1
            while left <= right and cnt['T'] > k and cnt['F'] > k:
                cnt[answerKey[left]] -= 1
                left += 1
            ans = max(ans, right - left + 1)
            
        return ans

LeetCode-1004. 最大连续1的个数 III

题意

  • 在一个由二进制数字(0 或 1)组成的数组中,找到一个最长的连续子数组,该子数组中最多包含 k 个 0。

算法步骤

  1. 初始化变量

    • ans:用来存储最大长度的结果。
    • left:滑动窗口的左边界。
    • cnt:用于统计 0 的个数,类型为 defaultdict(int)
  2. 遍历数组

    • 使用索引 right 遍历数组 nums,代表滑动窗口的右边界。
    • 当遇到数字 0 时,在 cnt 中将 0 的数量加一。
  3. 调整左边界

    • cnt 中 0 的数量超过 k 时,移动窗口的左边界 left,直至窗口中 0 的数量小于等于 k
    • 如果 nums[left] 为 0,则相应地将 cnt 中 0 的数量减一。
    • 左边界每移动一次,都需要更新 ans,记录最大子数组的长度。
  4. 返回结果

    • 遍历结束后,返回 ans,表示最长的满足条件的子数组长度。
class Solution:
    def longestOnes(self, nums: List[int], k: int) -> int:
        ans = 0
        left = 0
        cnt = defaultdict(int)

        for right, x in enumerate(nums):
            if x == 0:
                cnt[x] += 1
            while left <= right and cnt[x] > k:
                if nums[left] == 0:
                    cnt[nums[left]] -= 1
                left += 1
            ans = max(ans, right - left + 1)
        
        return ans

LeetCode-3090. 每个字符最多出现两次的最长子字符串

题意

  • 在给定字符串 s 中找到最长的子串,使得子串中任何字符的出现次数不超过 2 次。

算法步骤

  1. 初始化

    • ans:用来存储遍历过程中符合条件的最大子串长度。
    • left:滑动窗口的左边界。
    • cnt:字典,用来计数窗口内每个字符的出现次数。
  2. 遍历字符串

    • 使用变量 right 作为滑动窗口的右边界,并遍历字符串 s
    • 对于每个字符 x,增加 cnt[x] 的计数。
  3. 调整窗口左边界

    • 当某个字符 x 的计数达到 3 时,需要调整窗口的左边界 left,以确保窗口内所有字符的最大出现次数不超过 2。
    • 减少 s[left]cnt 中的计数,并将 left 向右移动。
  4. 更新结果

    • 在每次右边界向右移动后,更新 ans 的值,使其为当前窗口的长度和历史最长长度中的较大值。
  5. 返回结果

    • 遍历完成后,返回 ans 作为最终的结果。
class Solution:
    def maximumLengthSubstring(self, s: str) -> int:
        ans = 0
        left = 0
        cnt = defaultdict(int)

        for right, x in enumerate(s):
            cnt[x] += 1
            while left <= right and cnt[x] >= 3:
                cnt[s[left]] -= 1
                left += 1
            ans = max(ans, right - left + 1)
        
        return ans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值