代碼是用C寫的。
239. 滑動窗口最大值
使用單調雙端隊列記錄窗口內可能的最大值。
遍歷數組一次,由於是找窗口內的最大值,在窗口移動的過程中,需要把窗口內可能成爲接下來窗口最大值的數字先記錄在隊列中。
入窗口:每次有一個數字滑入窗口的時候,這個數字必定需要記錄在窗口內,因爲以這個數字爲起始位置的窗口是未知的,因此這個數字可能成爲窗口的最大值,當這個數字進入窗口後,我們需要對隊列裏候選的最大值進行判斷,如果發現先進隊列的數字比當前數字要小,那麼在當前數字成爲窗口內最大值候選的時候,比它小的數字就不可能成爲最大值,因此需要把這些數字彈出隊列。
每次進入隊列都進行上述判斷,因此隊列中的數字一定是按照從大到小的順序排列。由於隊列中的數字必定是在窗口內的,那麼此時窗口內的最大值就是隊列頭部的數字。
出窗口:當一個數字進入窗口,必定有另一個數字從窗口劃出,因此需要判斷出窗口的數字是否爲隊列的頭部,如果是,那麼從隊列中刪除,因此這個數字已經不在窗口內了,那麼必定不會成爲窗口最大值的候選。
例如:nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize){
int start=0,end=0,i;
int queue[numsSize+1];
int* rst=(int*)malloc(sizeof(int)*(numsSize+1));
if(k>numsSize)return NULL;
*returnSize=0;
for(i=0;i<numsSize;i++){
if(i>=k){
if(queue[start]==nums[i-k])start++;
}
while((end-start)>0){//隊列中有比當前放入的數字大的數,刪掉
if(nums[i]>queue[end-1]){
end--;
}
else
break;
}
queue[end++]=nums[i];
if(i>=k-1){
rst[*returnSize]=queue[start];
(*returnSize)++;
}
}
return rst;
}
567. 字符串的排列
這一題窗口大小不確定,每次窗口右端不斷擴大的時候判斷是否滿足了題目要求,如果還沒有滿足,判斷當前字符加入後,當前字符的數量在窗口內多了還是少了 ,如果少了,那麼繼續增大窗口右端;如果多了,那麼需要從窗口左端縮小,依次遍歷直到除去一個相同的字符。
bool checkInclusion(char * s1, char * s2){
int i,j,len1,len2,start=0;
len1=strlen(s1);len2=strlen(s2);
if(len1==0)return true;
if(len2==0)return false;
int letter[30],pat[30];
memset(letter,0,sizeof(letter));
memset(pat,0,sizeof(pat));
for(i=0;i<len1;i++){
letter[s1[i]-'a']++;
}
for(i=0;i<len2;i++){
pat[s2[i]-'a']++;
for(j=0;j<26;j++){//判斷當前子串是否符合要求
if(letter[j]==pat[j])continue;
else
break;
}
if(j==26)return true;
if(letter[s2[i]-'a']==0){//子串s2沒有當前字符。那麼子串重新開始選取
memset(pat,0,sizeof(pat));start=i+1;//start標記窗口的左側
}
else if(letter[s2[i]-'a']>=pat[s2[i]-'a']){//進入窗口,如果所選子串中當前字符還不夠,那麼直接加入即可
continue;
}
else{//出窗口,所選子串中當前字符出現的次數多了一次,需要在前面的串中去掉和當前字符一樣的數字
for(j=start;j<=i;j++){
pat[s2[j]-'a']--;start++;
if(s2[j]==s2[i])break;
}
}
}
return false;
}
76. 最小覆蓋子串
這一題和上一題類似,但是這一題只要保證串中有匹配串的所有字符即可,可以有其他的字符存在,題目要求最短滿足要求的串。思路和上面一題類似。
char * minWindow(char * s, char * t){
int i,j,len1,len2;
len1=strlen(s);
len2=strlen(t);
if(len2==0)return t;
if(len1==0)return "";
int letter[256],pat[256];
char* rstc=(char*)malloc(sizeof(char)*(len1+1));
memset(letter,0,sizeof(letter));
memset(pat,0,sizeof(pat));
for(i=0;i<len2;i++){
pat[t[i]]++;
}
for(i=0;i<len1;i++){//填充窗口,使得窗口內包含S2中的所有字符
letter[s[i]]++;
for(j=0;j<256;j++){
if(pat[j]<=letter[j])continue;
else
break;
}
if(j==256)break;
}
if(i==len1)return "";
int rst=len1;
int start=0,rstart=0,end=i;
for(j=start;j<=i;j++){
if(pat[s[j]]==0)start++;
else if(pat[s[j]]<letter[s[j]]){
letter[s[j]]--;start++;
}
else break;
}
if(rst>i-start+1){rst=i-start+1;rstart=start;end=i;}
i++;
for(i;i<len1;i++){
letter[s[i]]++;
if(s[i]==s[start]){
start++;
letter[s[i]]--;
for(j=start;j<=i;j++){
if(pat[s[j]]==0)start++;
else if(pat[s[j]]<letter[s[j]]){
letter[s[j]]--;start++;
}
else break;
}
if(rst>i-start+1){rst=i-start+1;rstart=start;end=i; }
}
}
for(j=rstart;j<=end;j++){
rstc[j-rstart]=s[j];
}
rstc[end-rstart+1]='\0';
return rstc;
}