一、42. 接雨水
题目链接:42. 接雨水 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——42. 接雨水
视频讲解:单调栈,经典来袭!LeetCode:42.接雨水_哔哩哔哩_bilibili
思路:找到底座,其左边第一个比它高的柱子和右边第一个比它高的柱子,形成凹槽,横向求解面积。
计算雨水面积:
h = min(h[ stack[ -1 ]](左面柱子的高度), h[ i ](右面柱子高度)) - h[ mid ](中间柱子高度)
w = i (右面柱子下标)- stack[ -1 ](左面柱子下标)- 1(只求中间一段宽度,再减一)
s = h * w
class Solution:
def trap(self, height: List[int]) -> int:
# 定义一个栈,存放下标,并将第一个元素入栈
stack = [0]
# 定义结果
result = 0
for i in range(1, len(height)):
# 当前遍历元素 < 栈口元素,直接把下标加入栈中
if height[i] < height[stack[-1]]:
stack.append(i)
# 当前遍历元素 = 栈口元素,依然加入栈中
elif height[i] == height[stack[-1]]:
# 有没有弹出的过程均可,不弹出会重复计算一次,但是不影响结果
stack.pop()
stack.append(i)
# 当前遍历元素 > 栈口元素,一直进行比较,并将栈中元素弹出,记录结果,注意需要判断栈不为空
else:
while len(stack) != 0 and height[i] > height[stack[-1]]:
# 存储中间元素下标
mid = stack[-1]
stack.pop()
# 因为有个弹出的操作,需要判断是否为空栈
if len(stack) != 0:
h = min(height[stack[-1]], height[i]) - height[mid]
w = i - stack[-1] - 1
s = h * w
result += s
stack.append(i)
return result
二、84.柱状图中最大的矩形
题目链接:84. 柱状图中最大的矩形 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——84.柱状图中最大的矩形
视频讲解:单调栈,又一次经典来袭! LeetCode:84.柱状图中最大的矩形_哔哩哔哩_bilibili
思路:每一个柱子找左面第一个比它矮的,右面第一个比它矮的柱子,计算形成矩形的面积,最后找最大值。
单调栈过程:需要 mid(基准的柱子,栈口元素), left, right 三个元素表示柱子,类似接雨水。单调递减栈。
Note:首尾要加个0,如果数组为单调递增,那么在单调递减栈中不会走到计算结果那一步。
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
# 在数组首加个0
heights.insert(0,0)
# 在数组尾加个0
heights.append(0)
# 初始化一个栈,并将第一位加入栈中
stack = [0]
# 初始化结果
result = 0
# 单调栈工作过程,注意单调递减栈
for i in range(1, len(heights)):
# 当前遍历元素 > 栈口元素,直接把下标加入栈中
if heights[i] > heights[stack[-1]]:
stack.append(i)
# 当前遍历元素 == 栈口元素,依然加入栈中
elif heights[i] == heights[stack[-1]]:
stack.pop()
stack.append(i)
# 当前遍历元素 < 栈口元素,一直进行比较,并将栈中元素弹出,记录结果,注意需要判断栈不为空
else:
while len(stack) !=0 and heights[i] < heights[stack[-1]]:
# 取中间柱子
mid = stack[-1]
stack.pop()
if stack:
# 左柱子为栈顶元素
left = stack[-1]
# 右柱子为当前元素
right = i
# 计算高度
h = heights[mid]
# 计算宽度
w = right - left - 1
# 计算面积
s = h * w
# 更新最大面积
result = max(result, s)
stack.append(i)
return result