滑动窗口最大值

题目:给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。
例如,如果输入数组{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]}。

分析:这个题目我个人认为除了暴力方法之外,一方面可以使用堆(优先队列)来解决这个问题,另一方面可以使用双端队列来解决问题。

先说一下使用双端队列来解决这个问题的思路吧,当然,也是从减脂offer上学到的。我们可以使用一个数组来存放我们最后需要返回的最大值序列,同时,我们使用一个双端队列来存放数组元素对应的下标(采用下标时,可以根据入队元素的下标来判断队头元素是否该出队)双端队列的存储里面有玄机,是解决问题的关键。首先,队头元素代表窗口内最大元素的下标。其次,每次入队的元素如果大于队头元素,则将队列中所有元素都出队,如果小于队头下标对应的元素,则尝试加入到队列中。同时若当前元素下标与队头元素的下标之差大于或等于size,则让队头元素出队。

import java.util.*;
public ArrayList<Integer> maxInWindows(int [] num, int size){
    ArrayList<Integer>result=new ArrayList<>();        
    if (num==null||num.length<size||size<1) {
        return result;
    }
    LinkedList<Integer> index=new LinkedList<>();//用于存放下标的双端队列
    for (int i=0;i<size;i++) {
        while(!index.isEmpty()&&num[i]>=num[index.getLast()]){//维护队列中最大值始终存放在队头
            index.removeLast();//队列不为空,且队尾元素小于需要入队的元素,则从队尾将元素删除
        }
        index.addLast(i);//从队尾进入队列
    }
    for (int i=size;i<num.length;i++) {
        result.add(num[index.getFirst()]);
        while(!index.isEmpty()&&num[i]>=num[index.getLast()]){
            index.removeLast();
        }
        if (!index.isEmpty()&&index.getFirst()<=i-size) {
            index.removeFirst();
        }
        index.addLast(i);
    }
    result.add(num[index.getFirst()]);    
}

使用堆来解决这个问题的思路,首先,我们可以get到数组和窗口大小size。那么我们可以将优先队列的大小设置为size,显然我们需要一个大顶堆来完成任务。窗口每移动一次,我们需要从堆中删除窗口中移出去的元素,同时向堆中加入移进窗口的元素。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值