剑指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]}。

解法1:

最直接的思路,遍历窗口,对于每个窗口,每次都重新计算,求出其最大值

import java.util.ArrayList;
public class Solution {
    ArrayList<Integer> maxInWindows(int [] num, int size){
        ArrayList<Integer> result = new ArrayList<Integer>();
        if(size==0) return result;
        int start = 0;
        int end = size-1;       
        while(end<num.length){
            result.add(getMax(num, start, end));
            start++;
            end++;
        }
        return result;
    }

    int getMax(int[] num,int start,int end){
        int max = -100000;
        for(int i=start;i<=end;i++){
            if(max<num[i]) max = num[i];
        }
        return max;
    }
}

解法2:

双端队列,在窗口滑动的过程中,维护一个队列,队列中的元素按照从小到大排序,因此有

  • 如果队列头结点在滑动窗口中,则丢列头的元素是当前最大值
  • 如果队列头不在滑动窗口范围内,应该移除掉。由于需要判断队列头是否在滑动窗口内,因此队列记录的是index,而不是值,但是通过index可以找到值。
  • 对于后加入队列的元素,如果比之前加入队列的元素大,则这些之前的元素,在后续的滑动中,不可能成为最大值,因此也可以移除
import java.util.ArrayList;
import java.util.LinkedList;
public class Solution {
    ArrayList<Integer> maxInWindows(int [] num, int size){
        ArrayList<Integer> result = new ArrayList<Integer>();
        if(size==0) return result;
        LinkedList<Integer> queue = new LinkedList<>();
        int index = 0;
        //检查前size-1个元素
        while(index<size-1 && index<num.length){
            //如果后面的元素比前面的大,则前面的元素不可能成为size中的最大,因此可以排除掉
            if(!queue.isEmpty() && num[queue.getLast()]<num[index]){
                queue.removeLast();
            }
            queue.addLast(index);
            index++;
        }
        //检查所有元素
        while(index<num.length){
            //如果后面的元素比前面的大,则前面的元素不可能成为size中的最大,因此可以排除掉
            while(!queue.isEmpty() && num[queue.getLast()]<num[index]){
                queue.removeLast();
            }
            queue.addLast(index);
            //检查第一个元素,是否超出滑动窗口,如果查出就移除掉
            if(index - queue.getFirst() + 1 > size){
                queue.removeFirst();
            }
            result.add(num[queue.getFirst()]);
            index++;
        }
        return result;
    }
}
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页