給你一個字符串 S、一個字符串 T,請在字符串 S 裏面找出:包含 T 所有字符的最小子串。
示例:
輸入: S = "ADOBECODEBANC", T = "ABC" 輸出: "BANC"
說明:
- 如果 S 中不存這樣的子串,則返回空字符串
""
。 - 如果 S 中存在這樣的子串,我們保證它是唯一的答案
1. 注意到題目的關鍵:"所有字母的最小子串",也就是說兩個串都只能是字母。
2. 於是,可以開闢一個大小爲64的數組,來存放數組中字母的頻率(Frequency)。準確的說,
通過字母的ASCII碼作爲數組的索引,開闢空間的大小爲26+6+26=58:26個大寫字母,26個小寫字母,
還有中間的6個非字母 A~Z[65~90] 非字母[91~96] a~z[97~122]
3. 滑動窗口的使用:分三種情況來移動窗口:(這裏令當前窗口的左右邊界分別爲l,r,窗口的大小爲winSize=r-l+1)
1) 當winSize < t.size() r++; 也就是窗口右邊界向右移動
2) 當winSize == t.size() :
2.1) 當窗口中的字符已經符合要求了,直接返回return,已經找到了
2.2) 否則r++,窗口右邊界向右移動
3) 當winSize > t.size()
3.1) 當窗口中的字符已經符合要求了,l++,窗口左邊界向右移動
3.2) 否則r++,窗口右邊界向右移動
#include <iostream>
#include <cstring>
using namespace std;
// 1) 當winSize < t.size() r++; 也就是窗口右邊界向右移動
// 2) 當winSize == t.size() :
// 2.1) 當窗口中的字符已經符合要求了,直接返回return,已經找到了
// 2.2) 否則r++,窗口右邊界向右移動
// 3) 當winSize > t.size()
// 3.1) 當窗口中的字符已經符合要求了,l++,窗口左邊界向右移動
// 3.2) 否則r++,窗口右邊界向右移動
string minWindow(string s, string t) {
int l = 0, r = -1;
int sFreq[64] = {0};
int tFreq[64] = {0};
int minl = 0, minr = s.size() + 1;
int flag;
int i;
if(s.size() < t.size()){
return "";
}
for(i = 0; i < t.size(); i++){
tFreq[t[i] - 'A']++;
}
while(true){
if(r - l + 1 < t.size()){
r++;
sFreq[s[r] - 'A']++;
continue;
}
flag = 0;
for(i = 0; i < 64; i++){
if(sFreq[i] < tFreq[i]){
break;
}
}
if(i == 64){
flag = 1;
}
else{
flag = 0;
}
if(r - l + 1 == t.size()){
if(flag == 1){
minl = l;
minr = r;
break;
}
else{
r++;
if(r >= s.size()){
break;
}
sFreq[s[r] - 'A']++;
continue;
}
}
if(r - l + 1 > t.size()){
if(flag == 1){
if(r - l < (minr - minl)){
minr = r;
minl = l;
}
sFreq[s[l] - 'A']--;
l++;
}
else{
r++;
if(r >= s.size()){
break;
}
sFreq[s[r] - 'A']++;
}
}
}
if(minr == s.size() + 1){
return "";
}
return string(s.begin() + minl, s.begin() + minr + 1);
}
int main(){
string s = "AB";
string t = "B";
string re = minWindow(s, t);
cout << re << endl;
return 0;
}