此博客为《代码随想录》单调栈章节的学习笔记,主要内容为单调栈接雨水问题的相关题目解析。
42. 接雨水
class Solution:
def trap(self, height: List[int]) -> int:
n = len(height)
stk = []
res = 0
for i in range(n):
while stk and height[i] > height[stk[-1]]:
mid = stk.pop()
if not stk: break
left, right = stk[-1], i
h = min(height[left], height[right]) - height[mid]
w = right - left - 1
res += h * w
stk.append(i)
return res
- 栈从栈顶到栈底递增,若当前元素 > 栈顶,则弹出栈顶元素;
- 此时如果栈不为空(为空则表明到达坐标轴边界了,无法接到雨水),则表明构成一个接雨水的区域:栈顶元素作为
mid,次顶元素作为left,当前元素作为right,统计面积
84. 柱状图中最大的矩形
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
heights = [0] + heights + [0]
n = len(heights)
res = 0
stk = []
for i in range(n):
while stk and heights[i] < heights[stk[-1]]:
mid = stk.pop()
left, right = stk[-1], i
h = heights[mid]
w = right - left - 1
res = max(res, h * w)
stk.append(i)
return res
- 与接雨水正好相反,找中间高两边低的三元组来画矩形
- 需要在原始
height数组中额外添加首尾两个0用于收集两个边界的结果(接雨水不需要添加因为边界无法收集雨水,但此题即使有边界也能够正常画出矩形) - 其余思路和接雨水类似
407. 接雨水 II
class Solution:
def trapRainWater(self, heightMap: List[List[int]]) -> int:
m, n = len(heightMap), len(heightMap[0])
h = []
for i, row in enumerate(heightMap):
for j, height in enumerate(row):
if i == 0 or i == m - 1 or j == 0 or j == n - 1:
h.append((height, i, j))
row[j] = -1 # 标记 (i,j) 访问过
heapify(h)
ans = 0
while h:
min_height, i, j = heappop(h) # min_height 是木桶的短板
for x, y in (i, j - 1), (i, j + 1), (i - 1, j), (i + 1, j):
if 0 <= x < m and 0 <= y < n and heightMap[x][y] >= 0: # (x,y) 没有访问过
# 如果 (x,y) 的高度小于 min_height,那么接水量为 min_height - heightMap[x][y]
ans += max(min_height - heightMap[x][y], 0)
# 给木桶新增一块高为 max(min_height, heightMap[x][y]) 的木板
heappush(h, (max(min_height, heightMap[x][y]), x, y))
heightMap[x][y] = -1 # 标记 (x,y) 访问过
return ans
- 三维接雨水,无法使用单调栈,此解法基于“短板效应”
930

被折叠的 条评论
为什么被折叠?



