每天五分钟:滑动窗口-LeetCode高频题解析_day3

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

把字符串想象成一排小格子,每格一个字母。

有一辆"窗口小火车"在这排格子上滑动,它有:

  • 左车门:left

  • 右车门:right

规则:

  • 火车载的乘客 = 当前子串里的字母

  • 不能有重名的乘客(无重复字符)

做法:

  1. right 每次往右走一格,把新字母拉上车

  2. 如果发现车里已经有同名乘客了

    → 就从左边寻找到同名乘客,都"请下车"(left = max(left, char_map[cur] + 1))

  3. 每一次火车停下来的时候,记录车里乘客人数(窗口长度)

  4. 记住历史上最多的一次乘客数,就是答案


核心算法思路(滑动窗口)

  • 用一个 setdict 记录窗口中出现的字符

  • right 往右走遍历字符串

  • s[right] 没出现在窗口中 → 直接加入

  • res = max(res, right - left) 更新答案

  • 若已经出现 → 移动 left到char_map中的同名索引;并从窗口中删字符

时间复杂度:O(n),每个字符最多进窗口一次、出窗口一次。

python 复制代码
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        char_map = {} #字典,用来存储每个字符最近出现的位置(索引)
        left = 0
        res = 0

        for right in range(len(s)):
            cur = s[right]
            if cur in char_map:
                res = max(res, right - left)
                # 注意这一步,非常重要!排除了虽然存在,但在窗口之外的
                left = max(left, char_map[cur] + 1)
            char_map[cur] = right
        
        return max(res, len(s) - left)

438. 找到字符串中所有字母异位词

"开一个长度等于 p 的小窗,

每挪动一步,更新窗里的字母数量,
只要数量表和 p 一样,这个位置就是答案。"


核心算法思路(定长滑动窗口)

  • 窗口长度固定为 k = len(p)

  • 用数组/字典统计 p 中每个字母的次数 need

  • 再用同样的结构维护窗口中每个字母的次数 window

  • 每次移动一格:

    • 右边加一个字母

    • 左边减一个字母(保证窗口长度始终为 k)

  • window == need,说明当前窗口是一个异位词 → 记录左端点

python 复制代码
from collections import Counter

class Solution:
    def findAnagrams(self, s: str, p: str):
        n, k = len(s), len(p)
        if n < k:
            return []

        need = Counter(p)
        window = Counter()
        res = []

        left = 0
        for right in range(n):
            # 把右边新字符加进窗口
            window[s[right]] += 1

            # 保持窗口长度为 k
            if right - left + 1 > k:
                window[s[left]] -= 1
                if window[s[left]] == 0:
                    del window[s[left]]
                left += 1

            # 长度刚好是 k 时,比较两边字母袋
            if right - left + 1 == k and window == need:
                res.append(left)

        return res

239. 滑动窗口最大值

有一个"魔法队伍",它只做两件事:

  1. 只保留可能成为最大值的同学

  2. 队伍里的数字从前到后是从大到小排好的

窗口往右移动时:

  • 新同学要进来时:

    • 把队尾比他小或等于他的同学全赶走(因为以后不可能当最大值)

    • 然后自己站到队尾

  • 如果队头同学已经"走出窗口范围"

    → 把他从队头移除

  • 每次窗口形成一个完整长度 k 后,

    → 队头的那位就是当前窗口的最大值


核心算法思路(单调队列 + 滑动窗口)

  • deque 存储的是 下标,不直接存值

  • 队列中的下标,对应的 nums[index]从大到小

  • 维护规则:

    1. 进新元素 i 前,从队尾把所有 nums[队尾] <= nums[i] 的下标弹出

    2. i 放入队尾

    3. 如果队头下标 < i - k + 1,说明已经不在当前窗口中,弹出队头

    4. i >= k - 1 时,开始记录答案:res.append(nums[deque[0]])

时间复杂度:O(n),每个元素最多入队一次出队一次。

python 复制代码
from collections import deque

class Solution:
    def maxSlidingWindow(self, nums, k: int):
        q = deque()   # 存下标,保持对应值单调递减
        res = []

        for i, x in enumerate(nums):
            # 1. 保持队列单调递减:新来的比队尾大,就把队尾弹掉
            while q and nums[q[-1]] <= x:
                q.pop()

            # 2. 把当前下标入队
            q.append(i)

            # 3. 如果队头已经滑出窗口左边,就弹掉
            if q[0] <= i - k:
                q.popleft()

            # 4. 当 i >= k-1 时,窗口已经形成,可以记录最大值
            if i >= k - 1:
                res.append(nums[q[0]])

        return res
相关推荐
沈浩(种子思维作者)1 小时前
真的能精准医疗吗?癌症能提前发现吗?
人工智能·python·网络安全·健康医疗·量子计算
MM_MS2 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
独自破碎E2 小时前
【二分法】寻找峰值
算法
njsgcs2 小时前
ue python二次开发启动教程+ 导入fbx到指定文件夹
开发语言·python·unreal engine·ue
io_T_T2 小时前
迭代器 iteration、iter 与 多线程 concurrent 交叉实践(详细)
python
mit6.8242 小时前
位运算|拆分贪心
算法
华研前沿标杆游学3 小时前
2026年走进洛阳格力工厂参观游学
python
Carl_奕然3 小时前
【数据挖掘】数据挖掘必会技能之:A/B测试
人工智能·python·数据挖掘·数据分析
ghie90903 小时前
基于MATLAB的TLBO算法优化实现与改进
开发语言·算法·matlab
恋爱绝缘体13 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit