首页 > 试题广场 >

滑动窗口的最大值

[编程题]滑动窗口的最大值
  • 热度指数:581430 时间限制: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)
function maxInWindows(num, size)
{
    // write code here
    let que = []//定义一个存最大值下标的双头队列,队首为最大值
    let res = []//存窗口最大值的数组
    const n = num.length
    for(let i =0;i<n;i++){
        if(i-que[0] >= size){//当维护的最大值不在窗口范围内时,将队首出队
            que.shift()
        }
        while(que.length>0 && num[que[0]]<=num[i]){//当新入队的值为最大值时,将队列清空
            que.shift()
        }
        while(que.length>0 && num[que[que.length-1]]<=num[i]){//当新入队的值比可能成为最大值的值大时,将比此值小的值出队
            que.pop()
        }
        que.push(i)//将此值入队
        
        if(i>=size-1){//将移动窗口中维护的最大值加入结果数组中
            res.push(num[que[0]])
        }
    }
    return res
}
module.exports = {
    maxInWindows : maxInWindows
};

发表于 2022-08-29 22:34:58 回复(0)
保存提交,报超时错,用例输入滚了几分钟都没到头
// 以下算法通过11/21组用例
function maxInWindows(num, size)
{
    if (!num) return null
    if (size > num.length || size <= 0) return []
    if (size === 1) return num
    if (size === num.length) {
        return [Math.max(...num)]
    }
    // write code here
    const res = []
    for(let i = 0; i < num.length; i++) {
        if (i + size > num.length) {
            break
        }
        const sizeArr = num.slice(i, i+size)
        const max = Math.max(...sizeArr)
        res.push(max)
    }

    return res
}
发表于 2022-07-30 09:43:40 回复(0)
function maxInWindows(num, size)
{
    // write code here
    if (size > num.length) return []
    // 维护一个非递增序列 stack
    let stack = [], ret = [], N = num.length;
    for (let i = 0; i < size; i++) {
        let val = num[i];
        if (stack.length == 0) {
            stack.push(val);
        } else {
            while (stack.length > 0 && stack[stack.length-1] < val) {
                stack.pop();
            }
            stack.push(val);
        }
    }
    ret.push(stack[0]);
    
    for (let i = size; i < N; i++) {
        let val = num[i], j = i-size;
        // 移动窗口左侧
        if (stack[0] == num[j]) {
            stack.shift();
        }
        // 窗口右侧
        while(stack.length > 0 && stack[stack.length-1] < val) {
            stack.pop();
        }
        stack.push(val);
        
        ret.push(stack[0]);
    }
    return ret;
}
发表于 2022-05-31 09:32:51 回复(0)
function maxInWindows(num, size) {
    // write code here
    if (!size || !num.length) return []

    let start = 0, res = []

    while (start + size <= num.length) {
        res.push(Math.max(...num.slice(start, start + size)))
        start++
    }

    return res
}
发表于 2022-03-09 11:34:54 回复(0)
function maxInWindows(num, size)
{
    // write code here
      var res=[];
    if(size==0)return res
  
    let i=0;
    while(i<=num.length-size){
        var count=0;
        for(let j=i;j<i+size;j++){
            count=Math.max(count,num[j])
        }
        res.push(count)
        i++;
    }
    return res
}
module.exports = {
    maxInWindows : maxInWindows
};
发表于 2021-12-20 17:39:15 回复(0)
function maxInWindows(num, size)
{
    // write code here
    let res = [];
    if(num.length<size||size==0){
        return res;
    }
    
    let pro = num;
    let len = pro.length;
    let sum = 0,list=[];
    
    while(len-size+1){
        let arr = pro.slice(0,size);
        pro = pro.slice(1,num.length);
        arr.forEach(item=>{
            sum+=item;
        })
        res.push(Math.max(...arr))//窗口的最大值
        list.push(sum);//求和
        len--;
    }
    //console.log(res);
    let max = 0;
    max = Math.max(...list);//取最大和
    //console.log(max);
    return res;
}
module.exports = {
    maxInWindows : maxInWindows
};

发表于 2021-11-23 19:45:27 回复(0)
function maxInWindows(num, size)
{
    let arr = []
    if (size === 0 || size > num.length) {
        return arr
    }
    for (let i = 0; i <= num.length - size; i++) {
        arr.push(Math.max.apply(Math, num.slice(i, i + size)))
    }
    return arr
}
发表于 2021-11-01 09:09:06 回复(0)
不太会用队列求解
function maxInWindows(num, size)
{
    var maxArray = [];
    var max = 0,count = 0,left = 0;
    // 判断 窗口大于数组长度或窗口长度为0的时候,返回空。
    if(num == null || num.length < size || size < 0) {
        return maxArray;
    }
    for (var i = 0; i < num.length; i++) {
        count++;
        if(count <= size) {
            if(num[i] > max) {
                max = num[i];
            }
        }
        // 如果计数等于窗口长度 那么就保存最大值
        if(count == size) {
            maxArray.push(max);
            // 考虑最大值在位于第一位的情况  向后滑动之后需要重新判断最大值  
            if(max == num[left]) {
                max = 0;
                // 判断剩下的两位里面的最大值
                for (var j = left + 1; j <= i; j++) {
                    if (num[j] > max ) {
                        max = num[j];
                    }
                }
            }
            left++;
            count--;
        }
    }
    return maxArray;
}    
module.exports = {
    maxInWindows : maxInWindows
};


发表于 2021-10-26 11:45:08 回复(1)
function maxInWindows(num, size)
{
    let k = size;
    if (k * num.length === 0) return [];

    let slidBar = [];
    for (let i = 0; i < (num.length - k + 1); i++) {
    let max = 0;
    for (let j = i; j < i + k; j++) {
        max = Math.max(max, num[j]);
    }
        slidBar.push(max)
    }
    return slidBar;
}


function maxInWindows(num, size){
    let k = size;
    if (k * num.length === 0) return [];
    const deque = [], res = [];
    for (let i = 0; i < num.length; i++) {
        while (deque.length && num[i] > deque[deque.length - 1]){
            deque.pop()
        }
        deque.push(num[i]);
        if (i >= k - 1) {
            res.push(deque[0]);
            if (num[i - k + 1] === deque[0]) deque.shift();
        }
    }
    return res;
};

发表于 2021-09-02 22:11:13 回复(0)
function maxInWindows(num, size)
{
    // write code here

var res=[]
if(size>num.length||size===0){
    return res
}
for(let i=0;i<num.length-size+1;i++){
  var max=num[i]
    for(let j=i;j<i+size;j++){
      
        if(num[j]>max){
            max=num[j]
        }
    }
    res.push(max)
}
    return res
}
module.exports = {
    maxInWindows : maxInWindows
};
发表于 2021-08-27 16:11:25 回复(0)
function maxInWindows(num, size)
{
    if(size === 0){
        return [];
    }
    let arr = [];
    while(num.length >= size){
        arr.push(num.slice(0, size));
        num.shift();
    }
    let maxArr = [];
    arr.forEach(i => {
        maxArr.push(i.sort((a, b) => b - a)[0]);
    })
    return maxArr;
}

发表于 2021-08-13 09:01:26 回复(0)

方法一:

function maxInWindows(num, size)
{
    const res = [];
    if (size > num.length || size <= 0) return res;
    for (let i = 0; i <= num.length - size; i++) {
        res.push(Math.max(...num.slice(i, i + size)));
    }
    return res;
}

方法二:

class TreeNode {
    constructor(val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

class Deque {
    constructor() {
        this.head = new TreeNode(0);
        this.tail = new TreeNode(0);
        this.head.right = this.tail;
        this.tail.left = this.head;
    }
    empty() {
        return this.head.right === this.tail;
    }
    front() {
        if (this.empty()) return null;
        return this.head.right.val;
    }
    pop_front() {
        const node = this.head.right;
        this.head.right = node.right;
        node.right.left = this.head;
        node.left = null;
        node.right = null;
        return node;
    }
    back() {
        if (this.empty()) return null;
        return this.tail.left.val;
    }
    push_back(value) {
        const node = new TreeNode(value);
        node.left = this.tail.left;
        node.right = this.tail;
        node.left.right = node;
        this.tail.left = node;
    }
    pop_back() {
        const node = this.tail.left;
        node.left.right = this.tail;
        this.tail.left = node.left;
        node.left = null;
        node.right = null;
        return node;
    }
}


function maxInWindows(num, size)
{
    const ret = [];
    if (!num || size < 1 || num.length < size) return ret;
    const dq = new Deque();
    for (let i = 0; i < num.length; i++) {
        while (!dq.empty() && num[dq.back()] < num[i]) {
            dq.pop_back();
        }
        dq.push_back(i);
        if (dq.front() + size <= i) dq.pop_front();
        if (i + 1 >= size) ret.push(num[dq.front()]);
    }
    return ret;
}
编辑于 2021-04-14 21:50:17 回复(0)
function maxInWindows(num, size)
{
    // write code here
    if(!num){
        return null;
    }
    var len = num.length;
    var arr = [];
    if(size > len || size <= 0){
        return arr;
    }
    if(size == 1){
        return num;
    }
    if(size == len){
        //注意这里用Math.max()的时候,如果直接传的是数组名,要在前面加...符号,不然不成功
        arr.push(Math.max(...num));
        return arr;
    }
    for(var i = 0;i < len - size + 1;i++){
        var num1 = [];
        num1 = num.slice(i,i+size);
        arr.push(Math.max(...num1));
    }
    return arr;
}
if好像写的有点多~

发表于 2021-03-23 16:48:24 回复(0)
法一: 暴力法
function maxInWindows(num, size)
{
    // write code here
    //暴力法:
    if(!num.length ||size == 0) return []
    let res = []
    for(let i = 0;i<num.length-size+1;i++){
        let temp = num.slice(i,i+size)
        let max = Math.max(...temp)
        res.push(max)
    }
    return res
    
}
法二: 单调队列
准备一个双端队列
从数组0位置到末尾遍历
如果队列中还没有元素#2位置,直接将新的元素加入到队列尾(addLast())
如果队列中已经有元素,而且当前遍历到的元素>=队列尾对应的元素#2位置 (注意:队列中添加的是数组的下标),弹出队尾元素,直到队尾元素不再小于当前元素
此时队列中队尾元素已经不小于当前遍历到的元素,再将当前遍历到的元素下标加入队列,这就保证了队列头一直是最大的(且从队列头到队列尾是递减的)
如果发现此时队列头已经在窗口之外了#3位置,就弹出队列头
如果发现此时窗口已经形成(当前遍历到的位置已经>=k-1:也就是初始状态的窗口右边界),就将队列头放入结果数组
循环结束
function maxInWindows(num, size)
{

    // 双端队列中保存的是元素下标,方便判断元素是否在当前滑动窗口中
        //  双端队列头元素对应的数字,就是当前滑动窗口的最大值
       //  双端队列头尾出入元素的时间复杂度是O(1)
    iif(!num.length || size == 0) return []
    let res=[];
    //这个队列储存索引
    let que=[];
    for(let i=0;i<num.length;i++){
        //确保队列中索引在滑动窗口内
        while(que.length>0 && que[0]<=i-size){//当当前窗口移出队首元素所在的位置,即队首元素坐标对应的num不在窗口中,需要弹出
            que.shift();
        }
        //确保该队列为单调队列
        while(que.length>0 && num[que[que.length-1]]<num[i]){//从后面依次弹出队列中比当前num值小的元素,同时也能保证队列首元素为当前窗口最大值下标
            que.pop();
        }
        que.push(i);//把每次滑动的num下标加入队列
        if(i>=size-1) res.push(num[que[0]]); //当滑动窗口首地址i大于等于size时才开始写入窗口最大值
    }
    return res;


}

编辑于 2021-01-21 16:13:34 回复(0)
//滑动窗口双指针
function maxInWindows(num, window)
{
    if(num.length==0||window==0||window>num.length){
        return [];
    }
    var list = [];
    var left=0;
    var right = window - 1;
    while(right<num.length){
        //获得本轮的窗口(数组)
        var windowArr = num.slice(left,right+1);
        //找到本轮的窗口的最大值
        var max = Math.max(...windowArr);
        //存入结果数组中
        list.push(max);
        //右移窗口进入下一次比较
        right++;
        left++;
    } 
   return list;
}


编辑于 2021-01-12 21:56:07 回复(0)