剑指Offer -- 滑动窗口的最大值

滑动窗口的最大值

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

//方法一:用一个变量保存最大值所在位置,向后滑动,将新增值与最大值比较
public ArrayList<Integer> maxInWindows(int [] num, int size){
    ArrayList<Integer> arr = new ArrayList<Integer>();
    if(num.length <= 0 || size <= 0) return arr;
    int p = -1;
    for(int i = 0; i < num.length - size + 1; i++){
        if( p < i){
            p = max(num, i, size);
            arr.add(num[p]);
        }
        else if( num[i+size-1] > num[p]){
            p =i + size - 1;
            arr.add(num[p]);
        }else
            arr.add(num[p]);
    }
    return arr;
}

private int max(int [] arr,int start,int len){
    int m = start;
    for(int i = 0; i < len; i++){
        if(arr[start + i] >= arr[m])
            m = start + i;
    }
    return m;
}

//方法二:用一个双端队列,队列第一个位置保存当前窗口的最大值,当窗口滑动一次
//1.判断当前最大值是否过期
//2.新增加的值从队尾开始比较,把所有比他小的值丢掉
import java.util.ArrayDeque;
public ArrayList<Integer> maxInWindows(int [] num, int size){
    ArrayList<Integer> res = new ArrayList<Integer>();
    if(size <= 0 || num.length == 0) return res;
    ArrayDeque<Integer> q = new ArrayDeque<Integer>();
    for(int i = 0; i < num.length; i++){
        if(q.isEmpty())
            q.add(i);       //i为滑动窗口内最新加入的位置
        else if(q.peekFirst() < i - size + 1)
            q.pollFirst();  //目前的最大值不在滑动窗口内
        while( !q.isEmpty() && num[q.peekLast()] <= num[i])
            q.pollLast();   //删除队列中小于最新值的位置
        q.add(i);           //将当前位置加入队列,队列中位置对应值为降序排列
        if( i - size + 1 >= 0)
            res.add(num[q.peekFirst()]);
    }
    return res;
}

猜你喜欢

转载自blog.csdn.net/liuheng94/article/details/81607777