什麼是單調棧,顧名思義,入棧時遵循單調原則。一般來說,可以求出乙個元素向右或向左能擴充套件的最大長度,保證該區間內該元素最大或最小。
假設我們有乙個整數數列a,元素分別為20, 10, 30,40。
對於第i個元素,我們要找到大於a[i]的第乙個元素的位置。
這就適合用單調棧的性質來求解,我們可以認為a[i+k]小於a[i]那麼就能繼續向右擴充套件,元素入棧,否則不能擴充套件,棧內元素出棧。
下面來模擬一下單調棧(單調遞減)的求解過程,我們要一直保持棧的單調性。
1:棧為空,20入棧
2:棧頂元素為20,10比20要小,10入棧
3:棧頂元素為10,30比10要大,如果加入30,那麼單調性會被破壞,10出棧。此時棧頂元素為20,如果加入30,還是會破壞單調性,故20出棧,這時棧為空,30入棧。
4:棧頂元素為30,40比30要大,如果加入40,破壞單調性,30出棧,40入棧。
那麼為什麼一直維持棧內元素的單調性就一定是對的呢,我們先假設棧中含有元素,並且一直保持單調遞減的。如果元素還沒有被彈出,那麼肯定是還沒有遇到比他大的元素。如果元素被彈出了,那麼一定是第一次遇到比他大的數了,不然元素早就被彈出了。
實現時,棧內實際上是儲存的元素的索引。這樣就能很快的定位。
for(遍歷陣列)
}
小q在週末的時候和他的小夥伴來到大城市逛街,一條步行街上有很多高樓,共有n座高樓排成一行。
小q從第一棟一直走到了最後一棟,小q從來都沒有見到這麼多樓,所以他想知道他在每棟樓的位置處能看到多少棟樓呢?
當前面的樓的高度大於等於後面的樓時,後面的樓將被擋住。
見**注釋
//
// created by panda on 2020/6/19.
///*
* 6* 5 3 8 3 2 5
* 3 3 5 4 4 4
* 從當前位置開始向左的乙個單調遞增序列長度加上向右邊的乙個單調遞增序列個數
* 向右看時:我們從最右邊開始掃瞄,然後維護乙個單調遞減的棧,這樣棧中元素的個數就是我們能看到的樓房棟數
* 向左看時:我們從最左邊開始掃瞄,同樣維護乙個單調遞減的棧,同樣棧中元素個個數就是我們能看到的樓房棟數
* 證明向右看時:如果要入棧的元素破壞了單調遞減的性質,那麼將要入棧的元素勢必要比棧頂元素要大,等價於高樓遮住了低樓
* 這樣從當前元素的左邊乙個看時,是不會看見破環了單調遞減性質的棧頂元素,就行3 勢必會破壞 2(棧頂), 5單調遞減棧的性質,
* 那麼從3右邊的第乙個8向右看時,絕對不會看到2,因為3(棧頂),2,5不會滿足單調遞減。
* 既然3的左邊第乙個都看不見,那麼3的左邊所有元素都會看不見
* 那麼2對於3左邊的元素來說就沒有貢獻了。
* 證明向右看時同理
*/#includeusing namespace std;
const int maxn = 100000 + 7;
int st[maxn]; //模擬棧,存放的時樓房的索引,這樣我們就能很快的知道是第幾棟樓
int left[maxn]; //left[i] 向左邊看時,能看到的樓房數
int right[maxn]; //right[i] 向右看時,能看到的樓房數
int building[maxn]; //building[i] 第i棟樓的高度
int top; //模擬棧頂指標
int n; //樓房總數
int main() else
}//2, 向左看
top = 0;
for (int i = 1; i <= n; i++) else
}for (int i = 1; i <= n; i++)
printf("\n");
}return 0;
}
單調棧 模板 單調棧模板
biu 單調棧主要用於求取左邊第乙個比它大,或者比它小的數。就比如站隊隨便排成一列,可以求到每個人後面第乙個比他高的人。同理可以推廣至右邊,比它矮均可。這就是單調遞增棧 遞減棧,從前至 棧,從後向前入棧的區別了。單調棧比較抽象,非常具有智慧型的想法,可應用的場景相當少,根據幾個經典題目體會它的用法會...
單調佇列 單調棧
參考文章 單調佇列 poj 2823 給定乙個數列,從左至右輸出每個長度為m的數列段內的最小數和最大數。數列長度 n 106 m n n 106,m n n 106 m n 直接暴力求解複雜度在0 mn 可以考慮維護區間最值,單調佇列則是維護區間佇列的強大 單調佇列的定義 單調佇列實現的大致過程 1...
棧和佇列 單調佇列 單調棧
講解部落格鏈結 一 單調棧 1 什麼是單調棧?單調棧是指乙個棧內部元素具有嚴格單調性 單調遞增,單調遞減 的一種資料結構。2 單調棧的兩個性質 滿足從棧頂到棧底具有嚴格的單調性 滿足後進先出的特徵,越靠近棧底的元素越早的進棧。3 元素進棧的過程 對於當前進棧元素x 如果x 棧頂元素,x 進棧。否則 ...