總結從名字上就聽的出來,單調棧中存放的資料應該是有序的,所以單調棧也分為單調遞增棧和單調遞減棧
單調遞增棧:資料進棧的序列為單調遞增序列
單調遞減棧:資料進棧的序列為單調遞減序列
ps:這裡一定要注意所說的遞增遞減指的是進棧的順序,而不是在棧中資料的順序,可能每個人的定義有所不同。
還有一點要注意,單調棧裡通常儲存的不是元素,而是元素的下標,不是單調棧裡的元素是有序的,而是單調棧存的元素(也就是下標)對應的元素是有序的
例如:有陣列[5,4,2],對應的單調棧為[0,1,2]出棧元素為 2,4,5
單調遞減棧偽**如下,相應的寫出單調增棧
stack<
int> st;
//此處一般需要給陣列最後新增結束標誌符,具體下面例題會有詳細講解
for(遍歷這個陣列)
else
當前資料入棧;
}}
用法:單調遞減棧,通常用於在遇到比前面元素大的資料時候,要更新結果的情況;單調遞增棧,通常用於遇到比前面元素小的資料時候,要更新結果的情況下。
為保證單調棧中元素全部彈出,對於要使用單調遞減棧時,在原來的陣列末尾新增乙個極大值int_max(或者其他比元素都大的數值);對於要使用單調遞增棧時,在原來的陣列末尾新增乙個極小值int_min(或者其他比元素都大的數值).
描敘:有n個人站隊,所有的人全部向右看,個子高的可以看到個子低的髮型,給出每個人的身高,問所有人能看到其他人發現總和是多少。
輸入:4 3 7 1
輸出:2
解釋:個子為4的可以看到個子為3的髮型,個子為7可以看到個子為1的身高,所以1+1=2
思路:暴力解法時間複雜度為o(n^2),
這是仔細觀察題目,在遇到比自己大的元素的時候就需要更新結果所以我們使用單調遞增棧來解決這個問題。
1.設定乙個單調遞增的棧(儲存元素下標)
2.當遇到大於棧頂的元素,開始更新之前不高於當前人所能看到的值
int
sumfield
(vector<
int> height)
else
v.push
(i);
//符合條件了就壓入}}
return sum;
}
此問題是乙個單向擴充套件的問題,比較簡單,只需要單調棧中的top(),沒有用到單調棧的top前面的元素,單調棧棧頂前面的元素表示了元素向左擴充套件的長度leetcode的題目
思路:暴力法:從當前元素往下找,直到末尾,那麼複雜度為n!,這個太暴力了;有個稍微暴力一些的,就是從當前的位置,向兩邊擴充套件,遇到比自己大的就持續擴充套件,遇到小的就停止更新,複雜度n2;
有第二個暴力思路可以聯想到單調遞增棧(遇到小就更新),注意這是個雙向擴充套件的問題,這個時候就要用到單調棧的top()和top()前那個元素,單調棧棧頂前面的元素表示了左邊第乙個比棧頂元素小的元素,是可以向左擴充套件的邊界
int
largestrectanglearea
(vector<
int>
& heights)
else
h.push
(i);
//不要忘了入棧}}
return sum;
}
當然這道題應該也能用動態規劃
1、當遇到找第乙個比自己大或者比自己小的問題時,可以考慮到單調棧;
2、遇到需要個邊界問題時,也能考慮用單調棧。
單調佇列或單調棧的學習及認識
顧名思義,資料是具有某方面的單調性質的 單增或單減等 單調佇列一般是用於優化動態規劃方面問題的一種特殊資料結構,且多數情況是與定長連續子區間問題相關聯。1.雙端佇列deque雙端佇列是一種線性表,遵守先進先出的原則。其支援下面四種操作 1 從隊首刪除 2 從隊尾刪除 3 從隊尾插入 4 查詢線性表中...
單調棧 模板 單調棧模板
biu 單調棧主要用於求取左邊第乙個比它大,或者比它小的數。就比如站隊隨便排成一列,可以求到每個人後面第乙個比他高的人。同理可以推廣至右邊,比它矮均可。這就是單調遞增棧 遞減棧,從前至 棧,從後向前入棧的區別了。單調棧比較抽象,非常具有智慧型的想法,可應用的場景相當少,根據幾個經典題目體會它的用法會...
單調佇列 單調棧
參考文章 單調佇列 poj 2823 給定乙個數列,從左至右輸出每個長度為m的數列段內的最小數和最大數。數列長度 n 106 m n n 106,m n n 106 m n 直接暴力求解複雜度在0 mn 可以考慮維護區間最值,單調佇列則是維護區間佇列的強大 單調佇列的定義 單調佇列實現的大致過程 1...