Problem: 76. 最小覆盖子串
文章目录
- 思路
- 相似滑动窗口题目 :
- Code
题目
给你一个字符串 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 的子串中,
因此没有符合条件的子字符串,返回空字符串。
思路
思路就是维护一个滑动窗口,窗口
[left,right]
,每次让right右端点右滑动,如果滑动到的字符是t串里面的,就让一个num(记录当前窗口中所包含的t中字符的个数)记录下,当num = t中字符个数,就开始收缩窗口,收缩窗口是从左边left收缩(left++),当收缩到的字符在t中存在,num–。
Note :
如果在每次开始收缩时记录当前的字符串,在266数据会卡内存,所以要改成记录子串的起始start,通过substr(start,len),获取最小子串。
相似滑动窗口题目 :
Code
class Solution {
public:string minWindow(string s, string t) {string ans = "" ;int n = s.size() ; int left = 0 , right = 0 ; int min_length = 10e5+1 ; int start = 0 ; int num = 0 ; // 记录当前窗口中所包含的t的字符个数unordered_map<char,int> window ;unordered_map<char,int> smap ; // 先计算出t串中的字符次数 for(char v : t) {smap[v]++ ; }while(right <n){char ch = s[right] ; // 右移动right++ ; if(smap.count(ch)){window[ch]++ ; if(window[ch] == smap[ch]){num++ ; // 包含数+1}}//当全部包含在内时while(num == smap.size()) {int cur_length = right-left ;if(cur_length < min_length){min_length = cur_length ;start = left ; // 直接记录ans 会卡内存// ans = s.substr(left,min_length) ; }char d = s[left] ; left++ ;if(smap.count(d)){if(window[d] == smap[d]) {num-- ; // 如果要去掉的是包含的}//收缩左边端点window[d]-- ; }}}if(min_length == 10e5+1) return "" ; return s.substr(start,min_length) ; }
};