1. 程式人生 > >滑動視窗(單調佇列)講解_legend

滑動視窗(單調佇列)講解_legend

雙端佇列的應用:
(一):長度為k的滑動視窗取最小值:(或者稱為單調佇列)
(二):多重揹包問題:
--------
(一)長度為k的滑動視窗取最小值:
(1)問題背景:slider window
有一個長度為n的陣列,有一個長度為k的滑動視窗,從左往右每次滑動一個元素;求出每次滑動視窗中的最小的元素。
如:n=5;k=3;a={1,3,5,4,2}
則輸出b={1,3,2};1是1,3,5中最下的,3是3,5,4中最小的;。。。


(2)思想:
(2.1)滑動視窗就是一個數組的長度為k的一部分;
(2.2)建立一個雙端佇列,該佇列是有序佇列,隊頭的元素最小;
(2.3)進佇列:如果當前元素比隊尾元素大,或者佇列為空,則直接進隊;
如果當前元素比隊尾元素小,則隊尾元素出隊,直至當前元素大於隊尾元素或佇列為空,然後當前元素入隊;
(2.4)出佇列:取每個視窗對應的最小值的時候,要保證隊頭元素在窗口裡面;
隊頭出列時,判斷隊頭元素是否在窗口裡面,如果在則直接輸出;否則,則一直出隊頭元素,直至所出的隊頭元素在窗口裡面,然後輸出。
(2.5)佇列中存取的是元素的下標,可以節省空間。
(2.6)一個單調佇列,末端插入,彈出,首端只彈出,不插入。隊首始終為最小值。
(2.7)如果新入隊的元素與隊頭元素的距離>=滑動視窗的寬度,則隊頭元素出佇列。


(3)雙端佇列的程式碼實現: o(n):
(3.1)問題:
給定n個元素,視窗寬度是m,隨著視窗的滑動,依次輸出窗中元素的最大值和最小值。
(3.2)思想:首先對前m個元素由小到大排序,於是最小值是排序後數列的頭元素,最大值是尾元素。移動視窗至下一格,排序好的數列插入一個元素,刪除一個元素,仍然保持單調性,於是最小值仍然是頭元素,最大值仍然是尾元素。
(3.3)複雜度:搜尋的時間複雜度是lgm(二分查詢),插入/刪除的時間複雜度是1(memcpy),進行n-m+1次,於是演算法的時間複雜度是O(nlgm)。


(3.4)程式碼實現:
http://blog.csdn.net/legend050709/article/details/36417145
--------
(二):多重揹包問題: