76. 最小覆蓋子串
解題思路:
本題採用滑動窗口的方法(事實證明,這效率有些低)。
- 首先定義兩個指針left和right,分別指向主串的兩邊位置
- 定義兩個hashTable ,一個用來記錄主串當前每個字符映射的個數,另一個是記錄模式串每個字符的個數
- 模式串每個字符對應的個數首先都要映射到一個hash表中,這個主要是用來當作判斷的一個籌碼。
- 遍歷主串中每一個字符,此時要對滑動窗口進行調整,每一個字符加進來,要擴大當前窗口的右指針,然後判斷當前窗口裏是否包含每一個模式串元素,如果包含,則嘗試縮小左指針,以減小窗口大小
- 最後要對邊界情況進行判斷,如模式串的字符個數比主串都少,和主串只有一個字符的情況
源代碼:
class Solution {
private:
unordered_map<char, int> ori, cnt;
public:
string deal_str(string s){
int resl = 0;
for(const auto &tmp : s){
if(ori.find(tmp) != ori.end()) return s.substr(resl, s.length() - resl);
}
return s;
}
bool check(){
for(const auto &tmp : ori){
if(cnt[tmp.first] < tmp.second) return false;
}
return true;
}
string minWindow(string s, string t) {
// 首先將匹配串的所有字符映射到hashtable中
for(const auto &tmp_char : t){
ori[tmp_char] ++;
}
// 這裏抖個機靈處理一下原始字符串,
// 不過我處理的好像不太對,沒個屌用。。
s = deal_str(s);
// 定義兩個指針 這裏resl一定要定義爲-1,因爲如果主串和匹配串都是一個字符,則其他數字就無法判斷了。
int l = 0, r = 0, resl = -1, min_len = INT_MAX;
// 將右指針向外擴張
while(r < s.length()){
// 先將字符壓入hash中
cnt[s[r]] ++;
// 將左指針向右收縮
while(check() && l <= r){
if(min_len > r-l+1){
min_len = r-l+1;
resl = l;
}
cnt[s[l]] --;
l ++;
}
r ++;
}
return resl == -1 ? "" : s.substr(resl, min_len);
}
};