← 返回编程题库
coding-min-window-substring困难免费版2000ms未尝试

最小覆盖子串

Minimum Window Substring

开始编码

做市数据 ops 团队在监控一个 tick 级事件日志 s——每个字符代表一种事件类型(如 'A'=主动买盘,'B'=订单簿更新,'C'=撤单)。对一个给定的告警模式 t,他们想找到 s最短的一段连续切片,使其包含 t 中要求的所有事件(按多重性计数t = "AABC" 要求切片中至少出现两次 A、一次 B、一次 C)。这段最短覆盖切片就是事后复盘要交给 review 的最紧证据窗口:再短就缺事件,再长就是冗余。

请实现 solution(s: str, t: str) -> str,返回 s 中能覆盖 t 全部字符(含多重性)的最短子串。若 t 为空,返回 ""。若 len(t) > len(s) 或不存在合法窗口,返回 ""长度相同时返回最左(起始下标最小)那个

示例 1solution("ADOBECODEBANC", "ABC") 返回 "BANC"。窗口 s[9..12] = "BANC" 覆盖 A、B、C 各一次,长度 4。s[0..5] = "ADOBEC" 也覆盖,但长度 6,输了。示例 2solution("aabaa", "aa") 返回 "aa"——多重性计数,必须包含两个 a;最左的两个连续 a 在 s[0..1]示例 3solution("abc", "abcd") 返回 "",因为 len(t) > len(s) 不可能覆盖。

朴素做法是枚举所有子串再检查覆盖,时间复杂度 O(n³),n = 10⁵ 时直接超时。关键技巧是双指针滑动窗口 + 两个多重集计数器need(从 t 统计的需求)和 window(当前 [l, r] 内的计数)。维护 have_count 表示已达到配额的不同字符种类数,窗口合法 iff have_count == len(need)r 扩张;窗口一变合法就记录长度并收缩 l 直到合法性被破坏。两个指针各自最多移动 n 次,总复杂度 O(n + m)。因为收缩阶段按左端点递增顺序枚举候选,仅在「严格更短」时更新最佳,「同长取最左」自然成立。

约束条件

  • 0 ≤ len(s) ≤ 100000
  • 0 ≤ len(t) ≤ 100
  • s 和 t 仅含 ASCII 字符
  • 若 t 为空字符串,返回 ""
  • 若 len(t) > len(s) 或 s 中没有任何窗口能(按多重性)覆盖 t 的全部字符,返回 ""
  • 若多个最短窗口长度相同,返回起始下标最小(最左)的窗口

样例

Case 1 · classic LC76 example

输入: ["ADOBECODEBANC","ABC"]

期望: "BANC"

需要覆盖 {A,B,C} 各一次。窗口 'BANC'(s[9..12])长度 4,是最短的合法窗口。'ADOBEC' 长度 6,'CODEBA' 不合法(缺 C),最终最短解是 'BANC'。

Case 2 · empty t

输入: ["abcdef",""]

期望: ""

t 为空字符串时没有需要匹配的字符,按规范直接返回 ""。

Case 3 · t longer than s — impossible

输入: ["abc","abcd"]

期望: ""

len(t) > len(s) 时不可能在 s 中找到覆盖窗口,返回 ""。

最近提交

还没有提交记录。

编码区

实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。

加载编辑器...
计时0:00

默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。

Case 1 · classic LC76 example

输入: ["ADOBECODEBANC","ABC"]

期望: "BANC"

需要覆盖 {A,B,C} 各一次。窗口 'BANC'(s[9..12])长度 4,是最短的合法窗口。'ADOBEC' 长度 6,'CODEBA' 不合法(缺 C),最终最短解是 'BANC'。

Case 2 · empty t

输入: ["abcdef",""]

期望: ""

t 为空字符串时没有需要匹配的字符,按规范直接返回 ""。

Case 3 · t longer than s — impossible

输入: ["abc","abcd"]

期望: ""

len(t) > len(s) 时不可能在 s 中找到覆盖窗口,返回 ""。