資料結構 單調棧

2021-10-25 03:22:52 字數 3599 閱讀 5751

這是筆者的第一篇部落格,由於筆者自身水平的限制。用詞可能不夠準確,句子不太通順,**水平可能也不太行,敬請指出,感激不盡!

我們都知道棧(stack)是一種先入後出的資料結構,而單調棧建立在棧的基礎上,它區別於普通的棧的特殊之處在於

棧中的元素一直保持著單調遞增/單調遞減的關係

比如單調遞增棧中的元素自棧底至棧頂元素(0~n-1)間都是單調遞增的,單調遞減棧中的元素都是單調遞減的。

為了加深印象,我們可以先以單調遞減棧為例,看乙個例子~

有一組數nums[6] = 按照如下規則進行操作:

如果棧為空/正在處理的數小於棧頂的數,則進棧;

如果正在處理的數大於棧頂的數,則將棧頂元素出棧,然後繼續進行判斷。

ok,首先我們將棧置空,然後再來乙個乙個地讀數。

首先讀到了10,此時棧為空,10進棧,現在棧的狀態:

讀到了1,棧頂元素為10,1<10,1進棧,棧的狀態:

讀到8,棧頂元素為1,8>1,那麼我們將1出棧;

繼續判斷,8<10,所以8進棧,棧的狀態:

讀到數12,棧頂元素為8,12>8,將8出棧;

繼續判斷,12>10,所以10出棧,此時棧已為空,將12進棧:

讀到6,6<12,進棧;

讀到4,4<6,將4進棧。

讀到這邊,相信讀者對單調棧的基本操作已經稍微有了解啦,那麼,單調棧有什麼用呢?

還是看上面的例子,假設我們用單調棧處理上面的陣列並且得到另外乙個陣列(假設陣列名為arr,並且將該陣列初始化為0),規定:在處理每個數(nums[i])之後,如果nums[i]保持在棧中,則將arr[i]自增1,那麼處理完整個陣列之後,得到的arr陣列應該是:,不難發現,arr[i]代表的含義是:

自第i個元素開始,從左往右數的連續的比它小的數的個數

通過單調棧的資料結構,我們可以很容易地得到這個陣列(很容易知道乙個元素附近的數和它之間的大小關係)(只需要o(n)的時間)。所以,如果問題中經常需要判斷陣列前後元素的大小關係,不妨採用單調棧的資料結構。

這樣看可能讀者理解不夠透徹,印象不夠深刻,那不妨一起來看道例題吧~

接雨水給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。

示例 1:

輸入:height = [0,1,0,2,1,0,1,3,2,1,2,1] 輸出:6 解釋:上面是由陣列

[0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。

示例 2:

輸入:height = [4,2,0,3,2,5]

輸出:9

看完題目之後我們可以先來分析一下,按照從左邊開始數第i個位置上可以盛放的水的量 = min(該柱子左邊最高柱子的高度,該柱子右邊最高柱子的高度) - 該柱子的高度。

方法一:

自左往右暴力列舉每個柱子左邊最高柱子的高度和右邊最高柱子的高度,相加最後可得結果。時間複雜度為o(n²)。

方法二:

不難看出我們需要經常比較每個位置柱子高度和其左右柱子高度,所以不妨建乙個單調棧來模擬這個過程:

(為了方便看,我們假設目前讀到的柱子高度為heights[i],棧中存放柱子的編號(自左往右0~n-1),棧的高度為size)

若棧為空(size==0)或 柱子高度小於棧頂柱子高度(heights[i] < heights[stack[size-1]]),則進棧;

若柱子高度大於等於棧底柱子(為此時左邊最高的柱子)高度(heights[i] >= heights[stack[0]]),棧中除棧底外的每個格仔可以多盛放heights[stack[0]] - heights[stack[j]] 個單位的雨水;

若柱子高度大於棧頂柱子高度且小於棧底柱子高度(heights[i] >= heights[stack[size-1]]),則棧頂元素對應的柱子可以多盛放heights[i] - heights[stack[size - 1]]個單位的雨水。(在更新了答案ans的值後,我們不妨令棧頂元素對應的柱子高度等於heights[i])

就上方第乙個例子做個示範:

讀入高度heights[0] = 0,進棧。

讀入高度heights[1] = 1,大於棧底元素,將棧底元素出棧(因為此時棧中只有乙個元素,所以不需要對ans進行操作),再將heights[1]進棧。

讀入元素heights[2] = 0,小於棧頂元素,進棧。

讀入元素heights[3] = 2,大於棧底元素,將棧中所有元素彈出,此時因為heights[2] = 0 而 heights[1] = 1 ,所以可以多盛 1-0=1個單位的雨水,將ans + 1。然後將heights[3]進棧。

讀入元素heights[4] = 1,進棧。讀入元素heights[5] = 0,進棧。

讀入元素heights[6] = 1,這裡heights[6] > heights[5] 且heights[6] < heights[3] 。我們將ans加上heights[6] - heights[5]之後,令heights[5] = heights[6] 。繼續判斷,heights[4] = heights[6] 。 heights[6]進棧。

讀入元素heights[7] = 3,這裡heights[7] > heights[3] (棧底元素)。所以要將棧中所有元素彈出,heights[4],heights[5],heights[6] 加上其與heights[3] 的差值,並且更新ans。然後將heights[7]進棧。

後面的步驟都只是重複前面的,所以這邊直接跳過。值得注意的是,最後棧中仍有五個元素,但因為右邊是空的,無法盛水,所以無需出棧,保持原樣即可。

**實現(c語言):

int trap(int* height, int heightsize)

stack[top] = i;

top++;}}

return ans;

}

限於筆者的水平,文章或者**中可能存在錯誤或者疏漏,請讀者不吝指正,感激不盡!

資料結構 單調棧

上班無事,刷力扣發現了個新名詞 單調棧 題目 496.下乙個更大元素 i 名字上就聽的出來,單調棧中存放的資料應該是有序的,所以單調棧也分為單調遞增棧和單調遞減棧 單調遞增棧 棧中資料出棧的序列為單調遞增序列 單調遞減棧 棧中資料出棧的序列為單調遞減序列 ps 這裡一定要注意所說的遞增遞減指的是出棧...

資料結構 單調棧

之前沒有寫過棧棧是只能在某一端插入和刪除的特殊線性表就像乙個桶一樣 我們可以用stl 也可以自己寫 進棧top 然後 stack top 進棧元素 退棧可以將退棧後的乙個元素賦值到乙個地方 top 單調棧故名思議 就是多了個 單調 的要求 以下文字引用於shuyu fang的部落格 若是單調遞增棧 ...

資料結構之單調棧

dev.c 資料結構之單調棧 從數學上來講,函式的單調性也可以叫做函式的增減性。當函式f x 的自變數在其定義區間內增大 或減小 時,函式值f x 也隨著增大 或減小 則稱該函式為在該區間上具有單調性。換句話來說,函式的單調性就是在區間內的自變數只增或只減。我們說,數學中函式在一段區間內自變數只增或...