1、單調棧
單調棧是指一個棧內部的元素具有嚴格單調性的一種數據結構,分為單調遞增棧和單調遞減棧。
其具有以下兩個性質:
1,滿足棧底到棧頂的元素具有嚴格單調性。
2,滿足棧的先進后出特性,越靠近棧頂的元素越后出棧。
元素進棧過程:
對於一個單調遞增棧來說,若當前進棧的元素為a,如果a<棧頂元素,則直接將a進棧。
如果a≥棧頂元素,則不斷將棧頂元素出棧,直到滿足a<棧頂元素。
模擬一個數列構造一個單調遞增棧
進棧元素分別為3,4,2,6,4,5,2,3。
圖片所示過程即為進棧過程。
實現單調棧STL棧和手寫棧均可。
2,單調隊列。
單調隊列與單調棧及其相似,把單調棧先進后出的性質改為先進先出既可。
元素進隊列的過程對於單調遞增隊列。
對於一個元素a,如果a>隊尾元素,那么直接將a扔進隊列,如果a≥隊尾元素,則將隊尾元素出隊列,直到滿足 a>隊尾元素即可。
實現用STL的雙端隊列即可(我好像一直都是手寫的)
由於雙端隊列即可以在隊頭操作,也可以在隊尾操作,那么這樣的性質就彌補了單調棧只能在一邊操作的不足。可以使得其左邊也有一定的限制。
3,時間復雜度分析
對於每個元素,其有且僅有一次插入,最多出現一次刪除,故其時間復雜度為O(n)。
練習:
給你n個數,讓你在這n個數中選出連續的m個數(m≤n),使這m個數的極差最小,若存在多個區間使得極差均最小,輸出最靠前的區間。
很顯然,$n≤10^4$時暴力明顯可做,$n≤10^6$時通過線段樹也可做,那如果n去到$10^7$呢?
我們考慮用單調隊列維護區間$[i,i+m-1]$的最小值和最大值,以下篇幅以維護最大值舉例。
首先,我們把前m個數扔進一個單調遞增隊列中,在扔進去的同時把這些數所對應的下邊也扔進去。顯然隊頭的數字即為區間[1,m]最大的數。
考慮基於[1,m]的數據去更新[2,m+1]的最大值。若第一個數依然存在於隊列中(很顯然若存在僅可能位於隊尾),將這個數刪除,然后將第m+1個數插入改單調隊列。顯然隊尾數字即為區間[2,m+1]的最大值。
重復該過程n-m+1次即可,顯然時間復雜度為O(n)。