题目:
纯C解决:
无非就是那几个步骤
1.构建判断是否符合条件的need表
2.构建跟随滑动窗口更新的window表
3.创建left和right用于滑动
4.根据滑动过程再适当的更新答案
只要耐心看完这个代码应该就能懂了
//【算法思路】滑窗+hash
//其实可以比喻left和right为窗口界定,而hash表中元素的增减操作,可以看作用于判断是否收缩窗口的工具,我亲切称其为橱柜。
char * minWindow(char * s, char * t){
int need[128]={0};
int window[128]={0};
int hash_len = 0;
//更新need橱柜
for(int i=0;t[i]!='\0';i++){
need[t[i]]++;
if(need[t[i]]==1){
//计算有多少个不同的字符(即哈希表的长度)
hash_len++;
}
}
int left=0,right=0;
//vali用于记录达到有效值的字符数
int valid=0;
int start=0,len=INT_MAX;
//开始滑动窗口
while(s[right]!='\0'){
//滑入窗口的字符,把它用变量单独存储,是需要right能够灵活的变化位置,后面的left也是一样
//比如这里的right实际上是每次扫描进橱柜的后一个位置,这样可以保证用right-left更新len不用考虑right的值是否要变换。
char c = s[right];
right++;
//右边扩大窗口
if(need[c]){
window[c]++;
if(window[c]==need[c])
valid++;
}
//当右边扩大到位后,开始收缩左窗口
while(valid==hash_len){
//更新最小覆盖子串
if(right-left<len){
start = left;
len = right-left;
}
//收缩左窗口,确保left所指的位置正是移出橱柜后的状态
char c = s[left];
if(need[c]){
window[c]--;
if(window[c]<need[c])
valid--;
}
left++;
}
}
//当len未更新时则说明不存在,故return "",否则为q。
char* q = s+start;
if(len==INT_MAX)
return "";
q[len]='\0';
return q;
}
C++解决:
唯一的区别就是比C多了很多的类和库
还有就是比C慢太多了。。当然也可以用数组作为hash表提高效率。这样和C的效率差距就不是很大了。
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char,int>need;
unordered_map<char,int>window;
for(char c:t)need[c]++;
int left=0,right=0;int valid = 0;
int len = INT_MAX;
int start = 0;
while(right<s.size()){
char c = s[right];
right++;
//右移窗口操作
if(need.count(c)){
window[c]++;
if(need[c]==window[c])
valid++;
}
//左移窗口操作
while(valid==need.size()){
//更新数据,使得len取最小
if(right-left<len){
start = left;
len = right-left;}
//移出窗口操作
char c = s[left];
if(need.count(c)){
window[c]--;
if(window[c]<need[c])
valid--;
}
left++;
}
}
return len==INT_MAX?"":s.substr(start,len);
}
};
滑动窗口的模板:
void slidingWindow(string s,string t){
unordered_map<char,int>need,window;
int left=0,right=0;
int valid=0;
while(right<s.size()){
//c是要移入窗口的字符
char c = s[right];
//右移窗口
right++;
//进行窗口内数据的一系列更新
...
/*** debug输出的位置 ***/
printf("window: [%d,%d]\n",left,right);
/********************/
//判断左窗口是否要收缩
while(window needs shrink){
//d是将移出窗口的字符
char d = s[left];
//收缩窗口
left++;
//进行窗口一系列数据的更新
...
}
}
}