C语言求解滑动窗口最大值
- 思路:单调队列:谈一下个人对单调队列的理解。比如说有10个元素,窗口宽度为4,在遍历这10个元素的时候,首先队列是空的,先将第一个元素放入队列,然后当遍历到第二个元素时,将第二个元素与队列里面的比较,如果第二个元素比第一个元素大,那么由于我是求一个滑动的连续的元素最大值,所以之后第一个元素不可能成为最大值,因为元素2存活周期(滑动窗口的宽度)长,并且比元素1大。因此我只需要维护一个单调递减得到队列即可。比如说我已经遍历到了第6个元素,队列中存放的是 2 3 5元素。而 2 > 3 > 6 > 5,这时候5元素就应该被淘汰,而6元素存进去。同时还需要考虑2元素是否超过存活周期,超过需要舍弃们也就是判断是否在窗口之外。
- 重点:
· 需要考虑传入参数的合法性 是否空
· 单调队列的维护
· 最开始几个元素由于窗口没有填满 不需要记录
- 坑人:题目中写的size<10 000,但是实际是 100 000!!!!
*
* @param num int整型一维数组
* @param numLen int num数组长度
* @param size int整型
* @return int整型一维数组
* @return int* returnSize 返回数组行数
*
* C语言声明定义全局变量请加上static,防止重复定义
*/
//先创建一个队列
static struct _queue{
int data[100000]; //队列数据
int head; //队列头
int tail; //队列尾
}que,ans;
int IsQueNull(){
if(que.tail-que.head==1)//之间距离1,说明空返回1
return 1;
else
return 0;
}
int* maxInWindows(int* num, int numLen, int size, int* returnSize ) {
//考虑滑动窗口为1,直接返回数组
if(num==NULL||numLen==0){
*returnSize=numLen;
return num;
}
//初始化返回值队列
ans.tail=0;
que.head=-1;//初始化队列头
que.tail=0;//初始化队列尾
//遍历num所有元素
for(int i=0;i<numLen;i++){
//首先判断队列是否为空,空队列直接入duilie
if(IsQueNull()==1){
que.data[que.tail++]=i;
}
//队列不为空 找到合适的位置入队列 只要新元素大于队列尾就弹出队列尾 最后入队列
else{
while(num[i]>=num[que.data[que.tail-1]])
{
//弹出队列尾元素 判断队列是否空
que.tail--;
if(IsQueNull()==1)
break;
}
//下标入队列
que.data[que.tail++]=i;
//此时需要判断 队列头部是否需要出队列,也就是队列头尾 是否超过了窗口宽度
if(i-que.data[que.head+1]==size)
que.head++;
}
//窗口元素满了 可以返回最大值了
if(i>=size-1){
ans.data[ans.tail++]=num[que.data[que.head+1]];
}
}
*returnSize=ans.tail;
printf("%d", numLen);
return ans.data;
}