代码是用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;
}