LeetCode-76.最小覆盖子串
- 互联网
- 2025-09-03 22:00:02

1、题目描述:
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。如果 s 中存在这样的子串,我们保证它是唯一的答案。示例 1:
输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC" 解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。示例 2:
输入:s = "a", t = "a" 输出:"a" 解释:整个字符串 s 是最小覆盖子串。示例 3:
输入: s = "a", t = "aa" 输出: "" 解释: t 中两个字符 'a' 均应包含在 s 的子串中, 因此没有符合条件的子字符串,返回空字符串。提示:
m == s.lengthn == t.length1 <= m, n <= 105s 和 t 由英文字母组成2、代码: class Solution { public: string minWindow(string s, string t) { // 如果字符串 s 或 t 为空,或者 s 的长度小于 t 的长度,直接返回空字符串 if (s.empty() || t.empty() || s.size() < t.size()) { return ""; } // need 哈希表:记录字符串 t 中每个字符的需求个数 unordered_map<char, int> need; // window 哈希表:记录当前窗口中每个字符的数量 unordered_map<char, int> window; // 初始化 need 哈希表,统计 t 中每个字符的出现次数 for (char c : t) { ++need[c]; } // 定义滑动窗口的左右边界 int left = 0, right = 0; // 记录最小覆盖子串的起始位置和长度 int start = 0, len = INT_MAX; // valid 变量:表示窗口中满足 need 条件的字符个数 int valid = 0; // 开始滑动窗口 while (right < s.size()) { // c 是将要移入窗口的字符 // 右边界向右扩展 char c = s[right++]; // 更新窗口内的数据 if (need.count(c)) { // 如果字符 c 在 need 中(即它是 t 中的字符) ++window[c]; // 将 c 加入窗口,并更新其计数 if (window[c] == need[c]) { // 如果窗口中 c 的数量达到了 need 中的需求 ++valid; // 满足条件的字符个数加一 } } // 判断左侧窗口是否需要收缩 while (valid == need.size()) { // 当窗口中的字符已经满足了 t 中所有字符的需求时 // 更新最小覆盖子串 if (right - left < len) { // 如果当前窗口比之前记录的最小窗口更小 start = left; // 更新最小窗口的起始位置 len = right - left; // 更新最小窗口的长度 } // d 是将要移出窗口的字符 // 左边界向右收缩 char d = s[left++]; // 更新窗口内的数据 if (need.count(d)) { // 如果字符 d 在 need 中 if (window[d] == need[d]) { // 如果窗口中 d 的数量刚好等于 need 中的需求 --valid; // 满足条件的字符个数减一 } --window[d]; // 将 d 移出窗口,并更新其计数 } } } // 返回结果 // 如果 len 仍然是 INT_MAX,说明没有找到符合条件的子串,返回空字符串 // 否则,返回从 start 开始长度为 len 的子串 return len == INT_MAX ? "" : s.substr(start, len); } };
3、解题思路:
1. 这是一个滑动窗口问题,需要 left 和 right 指针的滑动去遍历 s 字符串,首先创建2个无序的map(相当于哈希表,访问效率更高),一个need用来存储需要包含的字符种类及其数量(也就是 t 字符串),一个window用来存储 left 和 right 指针截取的 s 字符串中,所包含的字符种类及其数量。
2. 开始循环,循环条件是 right < s.size(),每次循环之前,都会进行 char c = s[right++] 操作,也就是提取 right 当前指向的 s 字符串的字符,并且 right++。
3. 开始扩充window,当 need 里面有 c 时,++window[c] ,如果 need[c] == window[c] 时,代表window 已经包含 need 里面的所有 c 字符了,那么 ++valid,也就是说,某个字符,已经完全满足。
4. 扩从不一定结束,但可以尝试开始收缩window,当valid == need.size()时,开始循环,收缩窗口,当right - left < len 时(哈希表是从 0 开始的,不需要 right - left + 1),更新start 、len的值,然后 char d = s [left++],当 need.count(d) 时,--window[d],当 window[d] == need[d]时,也就是不需要再收缩了,--valid,退出循环
LeetCode-76.最小覆盖子串由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“LeetCode-76.最小覆盖子串”
上一篇
Web开发技术概述