剑指offer25-滑动窗口的最大值******

265 阅读2分钟

滑动窗口的最大值

题目描述

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

思路

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

补充-Deque(双向队列)

  • 参考CSDN-Java 数据结构之Deque(双向队列)
    一个线性 collection,支持在两端插入和移除元素。名称 deque 是“double ended queue(双端队列)”的缩写,通常读为“deck”。大多数Deque 实现对于它们能够包含的元素数没有固定限制,但此接口既支持有容量限制的双端队列,也支持没有固定大小限制的双端队列。 此接口定义在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或false,具体取决于操作)。插入操作的后一种形式是专为使用有容量限制的 Deque 实现设计的;在大多数实现中,插入操作不能失败。
抛出异常 特殊值 抛出异常 特殊值
插入 addFirst(e) offerFirst(e) addLast(e) offerLast(e)
移除 removeFirst() pollFirst() removeLast() pollLast()
检查 getFirst() peekFirst() getLast() peekLast()