题目链接 76. 最小覆盖子串 - 力扣(LeetCode)
题目描述 给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
注意:
对于 t
中重复字符,我们寻找的子字符串中该字符数量必须不少于 t
中该字符数量。
如果 s
中存在这样的子串,我们保证它是唯一的答案。
输入输出样例 1 2 3 输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC" 解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
题目解释 首先,统计t
中所有字符的次数映射表numMap
,和字符总数。
然后两个指针l
和r
,指向目标字符串的左右两端,
找到s
中第一个t
中的字符下标作为起始的l
和r
numMap
对应字符
的数量减一,如果减为0
,那么字符总数减一。
移动r
指针扫描下一个,如果numMap
小于零,那么考虑是不是可以移动l
指针(我们只需要numMap <= 0
即可),如果r
移动到最后都不满足条件,返回空
代码 LeetCode101实现 C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 string minWindow (string S, string T) { vector<int > chars (128 , 0 ) ; vector<bool > flag (128 , false ) ; for (int i = 0 ; i < T.size (); ++i) { flag[T[i]] = true ; ++chars[T[i]]; } int cnt = 0 , l = 0 , min_l = 0 , min_size = S.size () + 1 ; for (int r = 0 ; r < S.size (); ++r) { if (flag[S[r]]) { if (--chars[S[r]] >= 0 ) { ++cnt; } while (cnt == T.size ()) { if (r - l + 1 < min_size) { min_l = l; min_size = r - l + 1 ; } if (flag[S[l]] && ++chars[S[l]] > 0 ) { --cnt; } ++l; } } } return min_size > S.size () ? "" : S.substr (min_l, min_size); }
官方实现
作者:力扣官方题解 链接:https://leetcode.cn/problems/minimum-window-substring/solutions/257359/zui-xiao-fu-gai-zi-chuan-by-leetcode-solution
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class Solution {public : unordered_map <char , int > ori, cnt; bool check () { for (const auto &p: ori) { if (cnt[p.first] < p.second) { return false ; } } return true ; } string minWindow (string s, string t) { for (const auto &c: t) { ++ori[c]; } int l = 0 , r = -1 ; int len = INT_MAX, ansL = -1 , ansR = -1 ; while (r < int (s.size ())) { if (ori.find (s[++r]) != ori.end ()) { ++cnt[s[r]]; } while (check () && l <= r) { if (r - l + 1 < len) { len = r - l + 1 ; ansL = l; } if (ori.find (s[l]) != ori.end ()) { --cnt[s[l]]; } ++l; } } return ansL == -1 ? string () : s.substr (ansL, len); } };