我們從最簡單的問題開始:
給定乙個長度為n的整數數列a(i),i=0,1,...,n-1和窗長度k.
要求:f(i) = max,i = 0,1,...,n-1
問題的另一種描述就是用乙個長度為k的窗在整數數列上移動,求窗裡面所包含的數的最大值。
解法一:
很直觀的一種解法,那就是從數列的開頭,將窗放上去,然後找到這最開始的k個數的最大值,然後窗最後移乙個單元,繼續找到k個數中的最大值。
這種方法每求乙個f(i),都要進行k-1次的比較,複雜度為o(n*k)。
那麼有沒有更快一點的演算法呢?
解法二:
我們知道,上一種演算法有乙個地方是重複比較了,就是在找當前的f(i)的時候,i的前面k-1個數其它在算f(i-1)的時候我們就比較過了。那麼我們能不能儲存上一次的結果呢?當然主要是i的前k-1個數中的最大值了。答案是可以,這就要用到單調遞減佇列。
單調遞減佇列是這麼乙個佇列,它的頭元素一直是佇列當中的最大值,而且佇列中的值是按照遞減的順序排列的。我們可以從佇列的末尾插入乙個元素,可以從佇列的兩端刪除元素。
1.首先看插入元素:為了保證佇列的遞減性,我們在插入元素v的時候,要將隊尾的元素和v比較,如果隊尾的元素不大於v,則刪除隊尾的元素,然後繼續將新的隊尾的元素與v比較,直到隊尾的元素大於v,這個時候我們才將v插入到隊尾。
2.隊尾的刪除剛剛已經說了,那麼隊首的元素什麼時候刪除呢?由於我們只需要儲存i的前k-1個元素中的最大值,所以當隊首的元素的索引或下標小於i-k+1的時候,就說明隊首的元素對於求f(i)已經沒有意義了,因為它已經不在窗裡面了。所以當index[隊首元素]
從上面的介紹當中,我們知道,單調佇列與佇列唯一的不同就在於它不僅要儲存元素的值,而且要儲存元素的索引(當然在實際應用中我們可以只需要儲存索引,而通過索引間接找到當前索引的值)。
為了讓讀者更明白一點,我舉個簡單的例子。
假設數列為:8,7,12,5,16,9,17,2,4,6.n=10,k=3.
那麼我們構造乙個長度為3的單調遞減佇列:
首先,那8和它的索引0放入佇列中,我們用(8,0)表示,每一步插入元素時佇列中的元素如下:
0:插入8,隊列為:(8,0)
1:插入7,隊列為:(8,0),(7,1)
2:插入12,隊列為:(12,2)
3:插入5,隊列為:(12,2),(5,3)
4:插入16,隊列為:(16,4)
5:插入9,隊列為:(16,4),(9,5)
。。。。依此類推
那麼f(i)就是第i步時佇列當中的首元素:8,8,12,12,16,16,。。。
單調佇列 DP
烽火傳遞 description 烽火台又稱烽燧,是重要的防禦設施,一般建在險要處或交通要道上。一旦有敵情發生,白天燃燒柴草,通過濃煙表達資訊 夜晚燃燒乾柴,以火光傳遞軍情。在某兩座城市之間有n個烽火台,每個烽火台發出訊號都有一定的代價。為了使情報準確的傳遞,在m個烽火台中至少要有乙個發出訊號。現輸...
單調佇列DP 斜率DP
考慮到知識點是單調佇列,考慮怎麼使用單調佇列 首先說明一點,小天使可以選擇當前時刻鋼琴是否移動 並非一次就要一段時間 考慮dp方程,由於每次只能走乙個方向,選擇不了,其實就相當於乙個一維的dp了 以往上 北 為例 t為第t段時間 f t i j max 變形為 f t i j max i 然後把 f...
單調佇列詳解
剛學單調佇列時,在網上各大部落格找文章學,說實話,寫得很雜,表示自己懵逼了些許,最後硬是啃出來了,所以我決定要寫一篇能讓大部分人都看懂的部落格來。說單調佇列,那我們就先說說這個單調佇列是個什麼物種。單調佇列從字面上看,無非就是 有某種單調性 的佇列,沒錯,這就是所謂的單調佇列。單調佇列 它分兩種,一...