單調棧的定義:
單調棧就是棧內元素單調遞增或者單調遞減的棧,單調棧只能在棧頂操作。
為了更好的理解單調棧,則可將單調棧用生活情形模擬實現,例如:
我們借用拿號排隊的場景來說明下。現在有很多人在排隊買可樂,每個人手裡都拿著號,越靠前的人手裡的號越小,
但是號不一定是連續的。小明拿了號後並沒有去排隊,而是跑去約會了。等他回來後,發現隊伍已經排得很長了,
他不能直接插入到隊伍裡,不然人家以為他是來插隊的。小明只能跑到隊伍最後,挨個詢問排隊人手裡的號,
小明認為號比他大的人都是「插隊」的,於是小明就會施魔法把這些人變消失,直到小明找到號比他小的為止。
在上面這個場景裡,大家排的隊伍就像是單調棧,因為大家手裡拿的號是單調遞增的。
而小明找自己位置的這個過程就是元素加入單調棧的過程。新加入的元素如果加到棧頂後,
如果棧裡的元素不再是單調遞增了,那麼我們就刪除加入前的棧頂元素,
就像小明施魔法把「插隊」的人變消失一樣。直到新元素加入後,棧依然是單調遞增時,我們才把元素加進棧裡。
(這樣做的目的是「維護」單調棧,是單調棧保持原來的單調性不變)
從陣列的角度闡述單調棧的性質:
給定乙個包含若干個整數的陣列,我們從第 1 個元素開始依次加入單調棧裡,並且加入後更新單調棧。
那麼單調棧有這樣的性質:對於單調遞增的棧,如果此時棧頂元素為 b,加入新元素 a 後進行更新時,
如果 a 大於 b,說明 a 在陣列裡不能再往左擴充套件了(由於單調棧的單調遞增性質,b前面的程式設計客棧元素均小於a),
也就是說,如果從 a 在陣列中的位置開始往左邊遍歷,則 a 一定是第乙個比 b 大的元素;
如果 a 小於 b,說明在陣列裡,a 前面至少有乙個元素不能擴充套件到 a 的位置(至少有b元素,因為b的值要大於a,如果此時再加入新的
a,那麼單調棧便不再單調,所以元素a此時不能壓入棧頂,因為這並不是元素a"應該"在的位置,只有當元素a找到自己的位置時
元素a方能壓入棧中,而這樣做的前提是不改變單調棧的單調性),也就是對於這些元素來說,a 是其在陣列右側第乙個比它小的元素。
單調棧的維護是 o(n) 級的時間複雜度,因為所有元素只會進入棧一vkpdgaxoz次,並且出棧後再也不會進棧了。
單調棧的性質:
1.單調棧裡的元素具有單調性
2.元素加入棧前,會在棧頂端把破壞棧單調性的元素都刪除
3.使用單調棧可以找到元素向左遍歷第乙個比他小的元素,也可以找到元素向左遍歷第乙個比他大的元素。
對於第三條性質的解釋(最常用的性質):
對於單調棧的第三條性質,你可能會產生疑問,為什麼使用單調棧可以找vkpdgaxoz到元素向左遍歷第乙個比他大的元素,
而不是最後乙個比他大的元素呢?我們可以從單調棧中元素的單調性來解釋這個問題,由於單調棧中的元素只能是單調遞增或者是單調
遞減的,所以我們可以分別討論這兩種情況(假設不存在兩個相同的元素):
1.當單調棧中的元素是單調遞增的時候,根據上面我們從陣列的角度闡述單調棧的性質的敘述,可以得出:
(1).當a > b 時,則將元素a插入棧頂,新的棧頂則為a
(2).當a < b 時,則將從當前棧頂位置向前查詢(邊查詢,棧頂元素邊出棧),直到找到第乙個比a小的數,停止查詢,將元素a
插入棧頂(在當前找到的數之後,即此時元素a找到了自程式設計客棧己的「位置」)
2.當單調棧中的元素是單調遞減的時候,則有:
(1).當a < b 時,則將元素a插入棧頂,新的棧頂則為a
(2).當a > b 時,則將從當前棧頂位置向前查詢(邊查詢,棧頂元素邊出棧),直到找到第乙個比a大的數,停止查詢,將元素a
插入棧頂(在當前找到的數之後,即此時元素a找到了自己的「位置」)
單調棧的介紹以及一些基本性質
單調棧就是棧內元素單調遞增或者單調遞減的棧,單調棧只能在棧頂操作。為了更好的理解單調棧,則可將單調棧用生活情形模擬實現,例如 我們借用拿號排隊的場景來說明下。現在有很多人在排隊買可樂,每個人手裡都拿著號,越靠前的人手裡的號越小,但是號不一定是連續的。小明拿了號後並沒有去排隊,而是跑去約會了。等他回來...
棧和佇列的基本性質
棧是一種特殊型別的線性表,訪問 插入 刪除只能發生在棧頂。vector繼承自list類,所以裡面有實現相關的介面,stack類是其中的乙個實現類。peek 返回棧頂元素,push 壓入棧,pop 刪除棧頂元素並且返回。佇列是一種 fifo先進先出的資料結構。元素被追加到佇列的末尾,從頭部進行刪除。p...
佇列和棧的基本性質和應用
棧和佇列在實現結構上可以有陣列和鍊錶兩種形式 陣列實現比較容易 用鍊錶結構比較複雜,因為有指標。棧結構的基本操作 pop 從棧頂彈出乙個元素 top或peek 只訪問棧頂元素,但是不彈出刪除 push 向棧頂壓入乙個元素 size 返回當前棧中的元素個數 佇列的基本操作 與站操作不同的是,push操...