一、题目描述
给定一个数组和滑动窗口大小,请找出所有滑动窗口里的最大值。
例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小为3,那么一共存在6个滑动窗口,它们的最大值分别为{4,4,6,6,6,5}
二、解题思路
申请一个windowMax数组,用来存放每一个窗口下的最大值
申请一个两端开口的队列,用来保存可能为滑动窗口中最大值的下标,这个队列的特点在于:
1)队首下标若无更新,则为当前滑动窗口最大值的下标,将此下标对应的元素加入windowMax数组中;
2)队尾元素下标出队的情况:当即将入队的下标对应的值大于队尾元素下标对应的值,则将队尾元素下标出队,直到队尾元素下标对应的值大于即将入队的下标对应的值将此下标入队;
3)队首元素下标出队的情况:若之前的滑动窗口最大值已经滑出了窗口但是它的最大值还在队首,需要讲这个队首元素强制出队,保证当前滑动窗口下新的最大值;
三、解题算法
/*****************************************************
author:tmw
date:2018-8-29
*****************************************************/
#include <stdio.h>
#include <stdlib.h>
void findMaxInWindow( int array[], int len, int size )
{
int kk=0;
/**参数合法性判断**/
if( array != NULL && len >= size && size >= 1 )
{
/**创建windowMax数组,用来存放每一个窗口的最大值**/
int windowMax[len];
for(kk=0; kk<len; kk++)
windowMax[kk] = 0;
int wind = 0;//windowMax数组的匹配游标
/**创建一个两端开口的队列,用来存放当前窗口下可能的最大值**/
int index[len];
for(kk=0; kk<len; kk++)
index[kk] = 0;
int ii=0; int jj=0; //i为前游标;j为后游标
int i=0;
/**开始以窗口为size做操作**/
for( i=0; i<size; i++ )
{
/**当队列非空且即将入队的元素下标对应的值大于当前队尾下标对应的值,则将当前下标出队,如此重复**/
while( ii!=jj && array[i]>=array[index[jj]] )
jj--; //相当于尾元素出队
index[++jj] = i;
ii++; //有效元素从第一位开始
}
for( i=size; i<len; i++ )
{
/**以size为窗口值的操作已经完成,接下来继续以size来挪动窗口,并且将当前窗口找到的最大值(队首元素)放到windowMax数组中**/
windowMax[wind++] = array[index[ii]]; //将上一个窗口的最大值加入数组,因此循环完后,记得补上将当前最大值加入数组
/**尾元素出队**/
while( ii!=jj+1 && array[i]>=array[index[jj]] )//因为前面已经约定有效位从第一位开始,当ii==jj时并不表示此队列为空,而是ii=jj+1
jj--; //相当于尾元素出队
/**更新首元素**/
if( ii!=jj+1 && array[index[ii]] <= array[i-size] )
ii++;
index[++jj] = i;
}
windowMax[wind] = array[index[ii]];
/**打印检查**/
for(i=0; i<len; i++)
printf("%d ",windowMax[i]);
}
}
变种1- 窗口size可变,求和大于等于给定值的最小窗口size
【题目描述】给定一个数组array和目标值target,找到连续子阵列的最小长度,使得它们的总和≥target。 如果没有,则返回INT_MAX。
【解题思路】
设定两个游标 start和end 初始位置都为0,初始化min_len = INT_MAX
1)当[start,end]的sum值小于target时,end++,并将更新后end指向的值加入总和sum
2)当[start,end]的sum值大于等于target时,更新并记录min_len = min(min_len,end-start),并将当前start指向的元素从sum中减掉,同时start++
3)直到start和end任意一个大于array_len 算法结束
/***********************************************
author:tmw
date:2018-8-30
***********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define min(a,b) (a<b?a:b)
int findMinWindowSize( int* array, int array_len, int target )
{
if( array == NULL || array_len < 0 ) return INT_MAX;
int start = 0;
int end = 0;
int sum = 0;
int min_len = INT_MAX;
while( start < array_len && end < array_len )
{
/**当[start,end]的sum值小于target时,end++,并将更新后end指向的值加入总和sum**/
while( sum < target && end < array_len )
sum += array[end++];
/**
当[start,end]的sum值大于等于target时,更新并记录min_len = min(min_len,end-start),
并将当前start指向的元素从sum中减掉,同时start++
**/
while( sum >= target && start <= end )
{
min_len = min( min_len, end-start );
sum -= array[start++];
}
}
return min_len;
}
梦想还是要有的,万一实现了呢~~~~ヾ(◍°∇°◍)ノ゙~~~~~~~~~~~~~~~~