滑动窗口求最大值数组

【题目】给出一个整形数组,例如arr = {5,4,3,5,6,7,6},窗口大小为w=3,窗口每次向右移动一位,输出每个窗口中最大值组成的数组。

package string;

import com.google.common.collect.Lists;

import java.util.Deque;
import java.util.LinkedList;
import java.util.Random;

/**
 * Created by cqs on 2018/3/17.
 */
public class MaxArray {

    private static Random random = new Random();


    public static void main(String[] args) {
//        int[] a = {4, 3, 5, 4, 3, 3, 6, 7};
        Integer[] a = {5, 4, 3, 5, 6, 7, 6};
        a = randArr(10);
        int windows = 3;
        Integer[] result = getMaxArray(a, windows);
        System.out.println(Lists.newArrayList(result));

    }

    /**
     * 使用双端队列存储数组索引
     * 队首是当前最大的值
     * 

*

* 遍历数组的时候 当下一个数的值小于队尾时候添加到队列尾部 * 当下一个数X大于等于队尾时 删除队尾元素 并继续和新的队尾比较 直到不大于队尾元素或者队列为空 * 然后添加X的索引到队列尾部 *

* 将队列首部元素(索引)对应数组的值存储到结果数组中 *

* 队列最多windows个元素 当队列超过windows个元素时 队首元素过期了 (窗口已经划过了) 需要删除队首元素 */ private static Integer[] getMaxArray(Integer[] a, int windows) { if (a == null || a.length < windows) return null; Deque queue = new LinkedList<>(); //处理第1个元素 至第windows -1个元素 queue.add(0); for (int i = 1; i < windows - 1; i++) { int fIndex = queue.getFirst(); if (a[i] > a[fIndex]) { queue.removeFirst(); queue.addFirst(i); } } //从第windows个元素开始 每次求出一个窗口最大值 Integer[] result = new Integer[a.length - windows + 1]; for (int i = windows - 1; i < a.length; i++) { //a[i]大于等于队尾的话 删除队尾元素 直到队尾元素大于a[i] 或者队列为空 while (queue.size() > 0 && a[queue.getFirst()] <= a[i]) { queue.removeLast(); } //队尾添加 queue.addLast(i); int fIndex = queue.getFirst(); result[i - windows + 1] = a[fIndex]; if (i - windows + 1 >= fIndex) { //本轮中窗口划过队首元素 queue.removeFirst(); } } return result; } private static Integer[] randArr(int size) { Integer[] as = new Integer[size]; for (int i = 0; i < size; i++) { as[i] = random.nextInt(100 * size); } System.out.println(Lists.newArrayList(as)); return as; } }

你可能感兴趣的:(滑动窗口求最大值数组)