1. 程式人生 > >面試題59-題目一:滑動視窗的最大值

面試題59-題目一:滑動視窗的最大值

/*

 * 面試題59-題目一:滑動視窗的最大值

 * 題目:給定一個數組和滑動視窗的大小,找出所有滑動窗口裡數值的最大值。

 * 例如,如果輸入陣列{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]}

 * 思路:就是採用雙端佇列,佇列中的頭節點儲存的資料比後面的要大。     

 * 比如當前假如的資料比隊尾的數字大,說明當前這個數字最起碼在從現在起到後面的過程中可能是最大值,

 * 而之前隊尾的數字不可能最大了,所以要刪除隊尾元素。     

 * 此外,還要判斷隊頭的元素是否超過size長度,由於儲存的是下標,所以可以計算得到;     

 * 特別說明,我們在雙端佇列中儲存的數字是傳入的向量的下標

 * 時間複雜度on),空間複雜度為on

 */

import java.util.ArrayList;

import java.util.LinkedList;

public class No59maxInWindows {

    public static void main(String[] args) {

       No59maxInWindows n = new No59maxInWindows();

       ArrayList<Integer> res = new ArrayList<Integer>();

       int[] a = { 2, 3, 4, 2, 6, 2, 5, 1 }; 

       res = n.maxInWindows(a, 3); 

        System.

out.print("最大值陣列為:"); 

        for (int i = 0; i < res.size(); i++) { 

            System.out.print(res.get(i) + " "); 

        } 

    }

    public ArrayList<Integer> maxInWindows(int[] num, int size) {

       ArrayList<Integer> res = new ArrayList<Integer>();

       if (num == null || size < 1 || num.length < size) {

           return res;

       }

       LinkedList<Integer> qMax = new LinkedList<Integer>();// 定義一個雙端佇列,保持的時陣列下標

       for (int i = 0; i < num.length; i++) {

           int cur = num[i];

           while (!qMax.isEmpty() && num[qMax.peekLast()] <= cur) {// 當雙端佇列不空,並且當前元素大於等於佇列的尾的元素時

              qMax.pollLast();// 把佇列尾部元素彈出

           }

           qMax.addLast(i);// 把當前陣列下標存到佇列中 

           if (qMax.peekFirst() == i - size) {// 當隊首的元素下標為i-w時,過期 

               qMax.pollFirst();// 將隊首元素彈出 

           }

           if (i >= size - 1) {// i=3size=3,此時視窗下標應為[1,2,3]index0,故此時index1,即視窗右移

              res.add(num[qMax.peekFirst()]);// 當前視窗的最大值,即視窗右移一位後的首部

           }

       }

       return res;

    }

}