又是一年招聘季,是时候好好复习一下算法了,也开始将以前写过的一些算法题进行一下回顾,顺便开始学习写一下博客吧
先把Leetcode上面的第76题,写一下
这道题主要是求在一个字符串S中查找包含字符串T中所有元素的最小子串。
For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC"
.
基本思想:
将T中各个字符计数到一个256的数组中,然后遍历S,当遇到T中字符时,对该字符的出现次数进行计数,如果当前记录的出现的次数小于T中该字符的个数,进行计数,否则不计数,
当计数器到达T的字符串长度时,说明找到答案,更新子串的起始和结束位置
但是该题的主要问题就在于怎么处理在count达到T.length后,就说明遇到了新的子串,
对子串大小的更新,这就主要根据val中得值进行判断了,通过初始化一个值p,用来消除多的元素
从p处开始往后走,对于遇到的每个字符判断是否当前子串已经多余了,直到遇到非多余的位置记录该位置为当前子串的起始位置,如果新的子串比历史最佳子串要小,进行更新。
如:在acbbaca中找abc的子串,当遇到第二个'a'时,第一个b就是多余的了,需要更新到第二个‘b’的位置
并用count计数有效字符出现的次数,当其与T的长度相等时,表明已经找到解,否则就无解
用p记录历史去重的位置,初始化为0
从头遍历S的每个字符c,当ct中存在c时,判断val[c]的值是否比ct[c]小,也就是判断c是否是新字符,是的话计数count++, 让val[c]自增
当count到达T的长度后,遇到新的T中字符时,就是出现了新的子串,从上次子串的位置开始剔除多余的元素,知道找到非多余元素的位置,判断最佳子串并更新
代码如下:
class Solution {
public:
string minWindow(string S, string T) {
int lenS = (int)S.size();
int lenT = (int)T.size();
int count=0;
int ct[256],val[256];
memset(ct, 0, sizeof(ct));//record origin each numbers of element
memset(val, 0, sizeof(val));//record numbers of each discoverd element
int start=0,end=lenS;
int p=0;
for(int i=0;i<lenT;i++){
ct[T[i]]++;
}
for(int i=0;i<lenS;i++){
char c = S[i];
if(ct[c]){
if(val[c] < ct[c]) count ++;//new element
val[c]++;
if(count >= lenT){//all elements are discovered
//omit all element excessed till element are useful
//just like “acbbaca” find "abc" when meet the second 'a' the point p need go to the second b,because the second b is
//excessed
while(val[S[p]] > ct[S[p]] || !ct[S[p]]){
val[S[p]] --;
p++;
}
if(end-start > i - p){//if the window is smaller,update it;
end = i;
start = p;
}
}
}
}
if(count < lenT){
return "";
}
return S.substr(start,end-start+1);
}
};