Desc: n/a
Overview
单调栈
定义;
能够解决的一类问题;
《程序员代码面试指南》CH1-栈与队列 – 单调栈结构
N/A
Leetcode#739. Daily Temperatures
N/A
Leetcode#769. Max Chunks To Make Sorted
N/A
Leetcode#?. Max Chunks To Make Sorted II
N/A
Leetcode#84. Largest Rectangle in Histogram
【描述】
Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]
.
The largest rectangle is shown in the shaded area, which has area = 10
unit.
【示例】
Input: [2,1,5,6,2,3]
Output: 10
【分析】
输入:上边界数组
过程:求出每个上边界的(能达到的最远)左右边界
实现:
- 遍历: O ( n 2 ) O(n^2) O(n2)
- 单调栈: O ( n ) O(n) O(n)
单调栈实现:
- 找出左边界的最近的比当前上边界小的位置(最近即能达到的最远)。
- 找出右边界的最近的比当前上边界小的位置。
得到每个 0,1,2,3,…,N-1 坐标的上边界高度对应的左右边界元组:
[ 2, 1, 5, 6, 2, 3 ]
index: 0 1 2 3 4 5 6(N)
[(0,1), (0,6), (2,4),(3,4),(2,6),(5,6)]
输出: max ( h e i g h t s [ i ] × ( b o r d e r [ i ] [ 1 ] − b o r d e r [ i ] [ 0 ] ) ) \max( heights[i] \times (border[i][1] - border[i][0]) ) max(heights[i]×(border[i][1]−border[i][0]))
过程实现分析:
- 右边界:
for r in range(len(heights))
;- 递增,push index(
r
); - 遇到小值,
border[<pop index>][1] = r
直到大于 pop 的 index,然后 push; - END 0->(N-1),
while stack: border[<pop index>][1] = <N>
。
- 左边界:
for l in range(len(heights) - 1, 0 - 1, -1)
;- 递增,push index(
l
); - 遇到小值,
border[<pop index>][0] = l
直到大于 pop 的 index,然后 push; - END (N-1)->0,
while stack: border[<pop index>][0] = 0
。
Solution:
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
if not heights: return 0
# calculate the border here:
border = [[-1, -1] for _ in range(len(heights))]
stack = []
# right ->->->
for r, h in enumerate(heights):
if not stack or h >= heights[stack[-1]]: # h >= heights[.pick()]
stack.append(r) # push
else:
while stack and h < heights[stack[-1]]: # h < heights[.pick()]
border[stack.pop()][1] = r
stack.append(r) # push
while stack:
border[stack.pop()][1] = len(heights)
# left <-<-<-
for l in range(len(heights)-1, 0-1, -1):
h = heights[l]
if not stack or h >= heights[stack[-1]]:
stack.append(l)
else:
while stack and h < heights[stack[-1]]:
border[stack.pop()][0] = l + 1
stack.append(l)
while stack:
border[stack.pop()][0] = 0
return max([heights[i] * (border[i][1] - border[i][0]) for i in range(len(heights))])
Submission:
Leetcode#85. Maximal Rectangle
将 matrix 按行计算“高度”。即按行转化为 84. Largest Rectangle in Histogram 问题。
Solution:
class Solution:
def maximalRectangle(self, matrix: List[List[str]]) -> int:
if not matrix: return 0
ans = []
for row in range(len(matrix)-1, 0-1, -1): # 0,1,2,...,(N-1) # NxM
heights = get_heights(matrix, row, len(matrix[row]))
ans.append(self.largestRectangleArea(heights))
return max(ans)
def largestRectangleArea(self, heights: List[int]) -> int:
# code 与 84. Largest Rectangle in Histogram 完全一致。
def get_heights(matrix, n, m):
ans = []
for _col in range(m):
h = 0
_row = n
while matrix[_row][_col] == '1' and _row >= 0:
h += 1
_row -= 1
ans.append(h)
return ans
Submission:
注:
求 heights 数组应该使用 DP 的方式,可以优化一点速度!!!
上面的矩阵就成这样了:
每一行都是一次柱状图的最大矩形面积了。dp[i][j]就是当前的第j列到第i行连续1的个数。
相关数据结构与算法
- 【Leetcode】栈与队列(待更新 #)
- 【Leetcode】二叉树与二叉树遍历算法(递归和迭代方案)(待更新 #)
- 【Leetcode】二叉搜索树与二叉搜索树搜索算法、插入算法、删除算法 (待更新 #)
- 【Leetcode】最小堆、最大堆(待更新 #)
- 【Leetcode】N-Tree 与遍历算法(递归与迭代方案)(待更新 #)
- 【Leetcode】链表(待更新 #)
- 【Leetcode】图(待更新 #)