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

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

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

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

  • 左车门:left

  • 右车门:right

规则:

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

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

做法:

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

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

    → 就从左边寻找到同名乘客,都"请下车"(left = max(left, char_mapcur + 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
相关推荐
Sirius.z4 小时前
第R6周:LSTM实现糖尿病探索与预测
python
名字还没想好☜4 小时前
Python f-string 进阶:数字格式化、对齐填充、调试 = 号与嵌套表达式
开发语言·数据库·python·字符串格式化·f-string
.道阻且长.4 小时前
2.LeetCode算法习题讲解--双指针--复写零
算法·leetcode·职场和发展
·薯条大王5 小时前
经济实惠玩云服务器|一台云服务器多人共用,子账号配置教程
java·linux·运维·服务器·汇编·c++·python
Dxy12393102166 小时前
Python 如何使用 MySQL 的事务
python·mysql
To_OC6 小时前
LC 438 找到所有字母异位词:暴力超时后,我靠滑动窗口一招搞定
javascript·算法·leetcode
Forever Nore9 小时前
学完C语言力扣第一题做不来正常吗
数据结构·算法
hansang_IR10 小时前
【题解】LC:倍增 / 区间并查集(Range Parallel Unionfind)
c++·算法·并查集
今儿敲了吗10 小时前
Python ——第三方包
笔记·python