首页 > 试题广场 >

滑动窗口的最大值

[编程题]滑动窗口的最大值
  • 热度指数:581493 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。

例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

窗口大于数组长度或窗口长度为0的时候,返回空。

数据范围: ,数组中每个元素的值满足 
要求:空间复杂度 ,时间复杂度


示例1

输入

[2,3,4,2,6,2,5,1],3

输出

[4,4,6,6,6,5]
示例2

输入

[9,10,9,-7,-3,8,2,-6],5

输出

[10,10,9,8]
示例3

输入

[1,2,3,4],5

输出

[]
推荐
import java.util.*;
/**
用一个双端队列,队列第一个位置保存当前窗口的最大值,当窗口滑动一次
1.判断当前最大值是否过期
2.新增加的值从队尾开始比较,把所有比他小的值丢掉
*/
public class Solution {
   public ArrayList<Integer> maxInWindows(int [] num, int size)
    {
        ArrayList<Integer> res = new ArrayList<>();
       	if(size == 0) return res;
		int begin;	
		ArrayDeque<Integer> q = new ArrayDeque<>();
		for(int i = 0; i < num.length; i++){
			begin = i - size + 1;
			if(q.isEmpty())
				q.add(i);
			else if(begin > q.peekFirst())
                q.pollFirst();
		
			while((!q.isEmpty()) && num[q.peekLast()] <= num[i])
                q.pollLast();
			q.add(i);	
			if(begin >= 0)
				res.add(num[q.peekFirst()]);
		}
		return res;
    }
}

编辑于 2015-09-02 14:11:26 回复(51)
完整队列实现,双指针游离
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
int *queue, queueSize, *topQueue=NULL, *bottomQueue=NULL;

void createQueue(int size) {
    queue = (int*)malloc(size*sizeof(int));
    memset((unsigned char*)queue, 0, size*sizeof(int));
    queueSize = size;
}

int top() {
    if(topQueue==NULL)
        return 0;
    return *topQueue;
}

int bottom() {
    if(bottomQueue==NULL)
        return 0;
    return *bottomQueue;
}

int len() {
    if(bottomQueue==NULL)
        return 0;
    if(topQueue <= bottomQueue)
        return bottomQueue-topQueue+1;
    else
        return queueSize-(topQueue-bottomQueue)+1;
}

int push(int node ) {   
    if(bottomQueue==NULL) {
        bottomQueue = queue;
        topQueue = queue;
    }
    else {
        if(topQueue-bottomQueue==1 || (topQueue==queue && bottomQueue==(queue+queueSize-1))) 
            return -1;
        
        if(bottomQueue == queue+queueSize-1) 
            bottomQueue = queue;
        else 
            bottomQueue++;
    }
    *bottomQueue = node;
    return 0;
}

int pop(int *node) {
    if(topQueue == NULL)
        return -1;
        
    if(node!=NULL)
        *node = *topQueue;
    *topQueue = 0;
    if(bottomQueue == topQueue) {
        bottomQueue = NULL;
        topQueue = NULL;
    }
    else {
        if(topQueue == queue+queueSize-1)
            topQueue = queue;
        else 
            topQueue++;
    }     
    return 0;
}

int max() {
    int res=top();
    int *q=topQueue;
    if(q!=NULL)
        while(q!=bottomQueue) {
            if(res<*q)
                res = *q;
            if(q == queue+queueSize-1)
                q = queue;
            else 
                q++;
        }
        if(res<*q)
            res = *q;
    return res;
}

int* maxInWindows(int* num, int numLen, int size, int* returnSize ) {
    int *res,i;
    if(size>numLen) {
        *returnSize = 0;
        return NULL;
    }
    if(size==0)
        return num;
    res = (int*)malloc((numLen-size+1)*sizeof(int));
    createQueue(size);
    for(i=0; i<numLen; i++) {
        if(push(num[i])){
            pop(NULL);
            push(num[i]);
        }
        if(i>=size-1) 
            res[i-size+1] = max();
    }
    *returnSize = numLen-size+1;
    return res;
}

编辑于 2024-03-19 18:06:16 回复(0)
这题不需要用太多数据结构的知识。不知道为什么这个题目会进入困难。普通数组的处理就行

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param num int整型一维数组 
 * @param numLen int num数组长度
 * @param size int整型 
 * @return int整型一维数组
 * @return int* returnSize 返回数组行数
 */
int* maxInWindows(int* num, int numLen, int size, int* returnSize ) 
{
    //num指向传入函数的数组,numLen为传入数组的长度。size为滑动窗口的大小
    // write code here
    //特殊情况校验
    if(size > numLen || size == 0)
    {
        return NULL;
    }

    // printf("%d",size);
    static int maxnum[10000];
    int max = -10000;  //暂时保存最大值
    //设定滑动窗口的起始和末尾初始定标
    int start = 0; int last = size;
    //在滑动窗口中找最大值。实际就是在后续每次比较把多进来的一个数值进行比较即可
    //进行第一轮定标。要把size大小内的元素都过一遍
    int flownum = numLen - size + 1;  //滑动窗口一共的滑动次数
    while(flownum)  //到0为最终结果
    {
        for(int i = start; i < last; i++)
        {
            if(num[i] > max)
            {
                max = num[i];
            }
        }
        maxnum[start] = max;  //找到滑动窗口的最大值
        (*returnSize)++;
        start++; last++;
        flownum--;
        max = -10000;  //每个滑动窗口内都会有不同的最大值。所以把max每次置为最小值就可以找到那个大值
    }

    return maxnum;
}

发表于 2023-10-02 14:54:11 回复(0)
int* maxInWindows(int* num, int numLen, int size, int* returnSize ) 
{
    if(size > numLen || size == 0)
    {
        return NULL;
    }
    int left = 0,right = size - 1; //确定窗口区间
    int max = num[0];
    *returnSize = numLen - size + 1;//确定返回数组数据个数

    int *res = (int *)malloc(sizeof(int) * (*returnSize));
    int k = 0;

    while(right < numLen)
    {
        for(int i = left;i <= right;i++)
        {
            if(max < num[i])
            {
                max = num[i];
            }
        }

        res[k++] = max;
        left++,right++;//改变窗区间并修改max值
        max = num[left];
    }

    return res;
}

发表于 2023-05-30 16:36:09 回复(0)
单调队列实现


/**
 *
 * @param num int整型一维数组
 * @param numLen int num数组长度
 * @param size int整型
 * @return int整型一维数组
 * @return int* returnSize 返回数组行数
 */

#include <stdbool.h>
#include <stdlib.h>
struct Deque {
    int queue_size;
    int *queue;
    int front_index;
    int back_index;
};

bool empty(struct Deque* dq)
{
    if (dq->front_index == dq->back_index) {
        return true;
    }
    return false;
}

int front(struct Deque* dq)
{
    return dq->queue[dq->front_index];
}

int back(struct Deque* dq)
{
    return dq->queue[dq->back_index - 1];
}

int pop_back(struct Deque* dq)
{
    int result;
    result = dq->queue[dq->back_index--];
    if (dq->back_index < 0) {
        dq->back_index = dq->queue_size - 1;
    }
    return result;
}

void push_back(struct Deque* dq, int value) {
    if (dq->back_index >= dq->queue_size) {
        dq->back_index = 0;
    }
    dq->queue[dq->back_index++] = value;
}

int pop_front(struct Deque* dq)
{
    int result;
    result = dq->queue[dq->front_index++];
    if (dq->front_index >= dq->queue_size) {
        dq->front_index = 0;
    }
    return result;
}

int* result = NULL;
int result_count = 0;

int* maxInWindows(int* num, int numLen, int size, int* returnSize ) {
    // write code here
    if (size > numLen) {
        return NULL;
    }
    if (size == 0) {
        return NULL;
    }
    struct Deque dq;
    dq.queue = (int*)malloc(sizeof(int)*(size + 2));
    dq.queue_size = size + 2;
    dq.back_index = dq.front_index = 0;

    result = (int*)malloc(sizeof(int)*(numLen - size + 1));
    for (int i = 0; i < numLen; i++) {
        while (!empty(&dq) && num[i] > num[back(&dq)]) {
            pop_back(&dq);
        }
        push_back(&dq, i);
        if (i - front(&dq) + 1 > size) {
            pop_front(&dq);
        }
        if (i >= size - 1) {
            result[result_count++] = num[front(&dq)];
        }
    }
    *returnSize = result_count;
    return result;

}

发表于 2023-03-08 20:23:37 回复(0)
int* maxInWindows(int* num, int numLen, int size, int* returnSize ) {
    // write code here
    if(size > numLen || size == 0)//窗口大于数组长度或窗口长度为0的时候,返回空。
        return NULL;
    int index = -1;//记录最大值的下标,防止出现更新的窗口最右边的数一直不大于原有的max
    int left = 0,right = size-1;
    int max = num[0];//保存最大值
    *returnSize = numLen - size + 1;//窗口的大小
    int *res = (int *)malloc(sizeof(int) * (*returnSize));
    int k = 0;

    while(right<numLen)
    {
        if(index<left)//下标小于left时没更新max,需更新max,index设置为-1也可进行循环
        {
            max = num[left];
            for(int i = left;i<=right;i++)
            {
                if(max < num[i])
                {
                    index = i;
                    max = num[i];
                }
            }
        }

        if(max<num[right])//此情况为窗口滑动一下就有比当前max更大的值进入窗口,更新max
        {
            max = num[right];
            index = right;
        }

        res[k++] = max;
        left++,right++;
    }
    return res;
}
简单易懂
发表于 2022-12-03 15:01:46 回复(0)
/**
 * 
 * @param num int整型一维数组 
 * @param numLen int num数组长度
 * @param size int整型 
 * @return int整型一维数组
 * @return int* returnSize 返回数组行数
 */
int* maxInWindows(int* num, int numLen, int size, int* returnSize ) {
    // write code here
    if(size > numLen || size == 0)
        return NULL;
    *returnSize = numLen - size + 1;
    int *p = (int *)malloc(sizeof(int) * size);
    int *q = (int *)malloc(sizeof(int) * (*returnSize));
    int i = 0,j,k = 0,m = 0;
    for(i = 0;i < *returnSize;i++)
    {
        for(j=i;j<size+i;j++)
            *(p+k++) = *(num+j);
        for(j = 1;j < size; j++)
            if(*(p) < *(p+j))
                *(p) = *(p+j);
        *(q+m++)  = *(p);
        k = 0;
    }
    return q;
}


发表于 2022-11-15 20:18:16 回复(0)
/**
 * 
 * @param num int整型一维数组 
 * @param numLen int num数组长度
 * @param size int整型 
 * @return int整型一维数组
 * @return int* returnSize 返回数组行数
 *
 * C语言声明定义全局变量请加上static,防止重复定义
 *
 * C语言声明定义全局变量请加上static,防止重复定义
 */

typedef struct alog
{
     int(*find_max_val)(int* ,int );
     void(*traverse_array)(struct alog,int*,int ,int,int* );
}alog_max;
static  int find_max_val(int* subarray,int win_size)
{
    int cnt = 0;
    int max_val = -1;
    for(;cnt<win_size;cnt++){
         if(max_val<subarray[cnt]){
             max_val = subarray[cnt];
         }
    }
    return max_val;
}
static  void traverse_array( struct alog my_alog,int* num,int numLen,int win_size,int* rst)
{
    int cnt = 0;
    for(;cnt<numLen-win_size+1;cnt++){
        rst[cnt] = my_alog.find_max_val(&num[cnt],win_size);
    }
}
static struct alog my_alog = {
    .find_max_val = find_max_val,
    .traverse_array = traverse_array,
};
int* maxInWindows(int* num, int numLen, int size, int* returnSize ) {
    // write code here
    if(numLen<size||size<0||num==NULL){
        return NULL;
    }
    int* rst = malloc(numLen*sizeof(int));
    my_alog.traverse_array(my_alog,num,numLen,size,rst);
    *returnSize = numLen-size+1;
    return rst;
}

发表于 2022-07-25 15:12:55 回复(0)
//队列思想解决
typedef struct elem{
    int num;
    int index;
}elem;
int* maxInWindows(int* num, int numLen, int size, int* returnSize ) {
    // write code here
    if(numLen<size || size ==0){
        return NULL;
    }
    if(size==1){
        *returnSize=numLen;
        return num;
    }

    *returnSize=0;
    int i,beg=0,end=0,*max;
    max = (int*)malloc(4*(numLen-size+1));
    elem arr[numLen+1];
    
    arr[0].num=num[0];  //当为空时
    arr[0].index=0;
    end++;

    for(i=1;i<size;i++){//第一个窗口
            if(arr[end-1].num>num[i]){
                arr[end].num=num[i];
                arr[end].index=i;
                end++;
            }else{
                int j;
                end--;
                for(j=end-1;j>=beg;j--){
                    if(arr[j].num<num[i]){
                        end--;
                    }
                }
                arr[end].num=num[i];
                arr[end].index= i;
                end++;
            }
    }
    (*returnSize)++;
    max[0]=arr[beg].num;

    for(i=size;i<numLen;i++){//其余窗口
        if(arr[beg].index<=i-size){
            beg++;
        }
        if(arr[end-1].num>num[i]){
                arr[end].num=num[i];
                arr[end].index=i;
                end++;
            }else{
                int j;
                end--;
                for(j=end-1;j>=beg;j--){
                    if(arr[j].num<num[i]){
                        end--;
                    }
                }
                arr[end].num=num[i];
                arr[end].index= i;
                end++;
            }
        max[(*returnSize)]=arr[beg].num;
        (*returnSize)++;
    }
    return max;
}

发表于 2021-09-09 20:38:09 回复(0)
/**
 * 
 * @param num int整型一维数组 
 * @param numLen int num数组长度
 * @param size int整型 
 * @return int整型一维数组
 * @return int* returnSize 返回数组行数
 */
int* maxInWindows(int* num, int numLen, int size, int* returnSize ) {
    // write code here
    int *pint1=num,*pint2=num+size-1,*temp=NULL;
    
     //int *returnArray=(int *) malloc((numLen-size+6)*sizeof(int));
   int *returnArray=(int *) malloc( numLen * sizeof(int));
    int tempArray[size];
    
    int i=0,j=0;
    if((size>numLen)||(size<=0))
        return NULL;
    
    *returnSize=numLen-size+1;
    
   
    while(pint2!=(num+numLen))
    {
        temp=pint1;
        while(temp!=(pint2+1))
        {
            tempArray[i]=*temp;
            temp++;
            i++;

        }
        for(i=0;i<size;i++)
        {
            if(tempArray[i]>returnArray[j])
                returnArray[j]=tempArray[i];
        }
        j++;
        i=0;
        pint1++;
        pint2++;
    }
    return returnArray;
}
发表于 2021-09-05 17:49:54 回复(0)