剑指offer_【64】滑动窗口的最大值

1.题目描述

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。

输入描述:

{2,3,4,2,6,2,5,1} ,3

输出描述:

{4,4,6,6,6,5}

解析:

存在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]}。
2.解题思路

我们可以使用双向队列(Linklist),队列中只存放当前元素的下标,

(1)设新来的元素为k,如果前面的元素比k小,直接把前面的删除(因为不可能成为后面窗口的最大值)

(2)如果前面的元素比k大,判断是否还在窗口范围内,不在则移除
以数组{2,3,4,2,6,2,5,1}为例
数组的第一个数字是2,把它存入队列中。

第二个数字是3,比2大,所以2不可能是滑动窗口中的最大值,因此把2从队列里删除,再把3存入队列中。

第三个数字是4,比3大,同样的删3存4。

此时滑动窗口中已经有3个数字,而它的最大值4位于队列的头部。

第四个数字2比4小,但是当4滑出之后它还是有可能成为最大值的,所以我们把2存入队列的尾部。

第五个数字是6,比4和2都大,删4和2,存6。就这样依次进行,最大值永远位于队列的头部。
3.代码
public static ArrayList<Integer> maxInWindows(int [] num, int size) {
    ArrayList<Integer> arr = new ArrayList<>();
    if (num==null)
        return arr;
    if (num.length<size||size<=0)
        return arr;
    Deque<Integer> queue = new LinkedList<>();
    for (int i = 0; i<num.length; i++){
     //如果前面的数比插入的数小,直接把前面删除(因为不可能成为后面窗口的最大值)
        while (!queue.isEmpty()&&num[i]>=num[queue.getLast()])
            queue.pollLast();
        //如果前面的元素比k大,判断是否还在窗口范围内,不在则移除
        //(i-(size-1))即滑动窗口最左侧的坐标索引
        while (!queue.isEmpty()&&queue.getFirst()<i-(size-1))
            queue.pollFirst();
        //加入队尾
        queue.offerLast(i);
        if (i+1>=size)
            arr.add(num[queue.getFirst()]);
    }
    return arr;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值