您當前的位置:首頁 > 攝影

單調棧演算法

作者:由 工藤新木 發表于 攝影時間:2022-09-21

一、單調棧的概念

從棧底元素到棧頂元素呈單調遞增或單調遞減,棧內序列滿足單調性的棧。

二、單調棧演算法舉例

LeetCode_84柱狀圖中最大的矩形(

https://

leetcode-cn。com/problem

s/largest-rectangle-in-histogram/

給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度為 1 。

求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。

以下是柱狀圖的示例,其中每個柱子的寬度為 1,給定的高度為 [2,1,5,6,2,3]。

圖中陰影部分為所能勾勒出的最大矩形面積,其面積為 10 個單位。

示例:

輸入: [2,1,5,6,2,3]

輸出: 10

單調棧演算法

按照單調棧的思路,遞增時入棧,其餘時計算面積並出棧,直到繼續遞增時入棧。面積將透過計算當前位置和棧頂元素所在位置的寬度查,再乘上元素的height值的思路來做這題:

class Solution {

public int largestRectangleArea(int[] heights) {

// 兩個棧,一個存位置,一個存值

Stack posStack = new Stack<>();

Stack valueStack = new Stack<>();

posStack。push(-1);

valueStack。push(-1);

int maxArea = 0;

for (int i = 0; i <= heights。length; i++) {

// 當前值比棧頂大,即壓棧

if (i < heights。length && heights[i] >= valueStack。peek()) {

posStack。push(i);

valueStack。push(heights[i]);

}

else {

// 已到頭了,挨個向前把每個面積都算一下

if (i >= heights。length) {

while (posStack。peek() != -1) {

int value = valueStack。peek();

valueStack。pop();

posStack。pop();

int area = value * (i - posStack。peek() - 1);

maxArea = area > maxArea ? area : maxArea;

}

}

// 未到頭時,當前值比棧頂小的,則向前計算面積,直到比棧頂大,壓棧

else {

while (heights[i] < valueStack。peek()) {

int value = valueStack。peek();

valueStack。pop();

posStack。pop();

int area = value * (i - posStack。peek() - 1);

maxArea = area > maxArea ? area : maxArea;

}

posStack。push(i);

valueStack。push(heights[i]);

}

}

}

return maxArea;

}

}

這道題說起來花了不少時間,從理解思路,到實際寫程式碼,寫程式碼時有兩個用例又沒透過,再重新除錯對了思路。直到最後現在的結果。

單調棧演算法

其實可以做一些程式碼最佳化,少一個棧空間,程式碼做下抽去方法的精簡,但其實我覺得沒太大的必要,可以看下最佳化的:

class Solution {

public int largestRectangleArea(int[] heights) {

// 初始化棧,存位置-1,壓底

Stack posStack = new Stack<>();

posStack。push(-1);

// 最大面積

int maxArea = 0;

for (int i = 0; i <= heights。length; i++) {

// 當前值比棧頂大,即壓棧

if (i < heights。length && heights[i] >= (posStack。peek() == -1 ? -1 : heights[posStack。peek()])) {

posStack。push(i);

}

else {

// 已到頭了,挨個向前把每個面積都算一下

if (i >= heights。length) {

while (posStack。peek() != -1) {

maxArea = getMaxArea(posStack, maxArea, i, heights[posStack。peek()]);

}

}

// 未到頭時,當前值比棧頂小的,則向前計算面積,直到比棧頂大,壓棧

else {

while (heights[i] < (posStack。peek() == -1 ? -1 : heights[posStack。peek()])) {

maxArea = getMaxArea(posStack, maxArea, i, (posStack。peek() == -1 ? -1 : heights[posStack。peek()]));

}

posStack。push(i);

}

}

}

return maxArea;

}

private int getMaxArea(Stack posStack, int maxArea, int i, int height) {

posStack。pop();

int area = height * (i - posStack。peek() - 1);

return area > maxArea ? area : maxArea;

}

}

三、單調棧整體思路

單調棧主要運用在給你一個數組序列,在遍歷陣列時,需要向前檢視元素的這種情況,此時將前面的元素入棧,形成單調棧。具體再結合題目的用意,加以利用。

整體思路還是在於自己看如何利用單調棧,有一定的難度。

其它單調棧題解:

工藤新木:柱狀圖中最大的矩形(單調棧)

工藤新木:每日溫度(單調棧)

工藤新木:下一個更大元素 II(單調棧)

工藤新木:最大矩形(單調棧)

工藤新木:接雨水(單調棧)

工藤新木:股票價格跨度(單調棧)

工藤新木:最大寬度坡(單調棧)

如有錯誤,請更正指出,謝謝!

標簽: posStack  heights  int  maxArea  PEEK