第 40 课
- 84.柱状图中最大的矩形
- 85.最大矩形
84.柱状图中最大的矩形
计算每一根柱子高度构成的最大矩形面积,即作用范围 * 高度。每根柱子向左右扩展寻找它作为最小值的作用范围。
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
q, n, h = [], len(heights), heights
# 方法一:用两个列表保存边界,即左右边界分开确定。
# left, right = [-1] * n, [n] * n
# for i in range(n):
# while q and h[q[-1]] > h[i]: # i 是栈顶的右边界
# right[q.pop()] = i
# if q: left[i] = q[-1] # 当前栈顶是 i 的左边界
# q.append(i)
# # 统计每根柱子作为最小值的面积
# ans = max((right[i] - left[i] - 1) * h[i] for i in range(n))
# 方法二:计算当前栈顶的贡献值
for i, x in enumerate(h + [-1]): # 哨兵 最后无法确定右边时使用
while q and h[q[-1]] > x:
j = q.pop()
# 栈空左边界取 -1,不空取栈顶、右边界是 i,计算 j 的贡献值。
ans = max(ans, h[j] * (i - (q[-1] if q else -1) - 1))
q.append(i)
return ans
class Solution {
public int largestRectangleArea(int[] heights) {
int n = heights.length, ans = 0; int[] h = heights;
Deque<Integer> q = new LinkedList<>();
// int[] a = new int[n], b = new int[n];
// Arrays.fill(b, n);
// for (int i = 0; i < n; i++){
// while (!q.isEmpty() && h[i] < h[q.peek()])
// b[q.pop()] = i; // i 作为弹出元素的右边界
// a[i] = q.isEmpty() ? -1 : q.peek();
// q.push(i);
// }
// for (int i = 0; i < n; i++){
// ans = Math.max(ans, (b[i] - a[i] - 1) * h[i]);
// }
for (int i = 0; i <= n; i++){ // i == n 不能确定右边时使用
while (!q.isEmpty() &&(n == i || h[i] < h[q.peek()])){
int j = q.pop(), k = q.isEmpty() ? -1 : q.peek();
ans = Math.max(ans, h[j] * (i - k - 1));
}
q.push(i);
}
return ans;
}
}
85.最大矩形
class Solution:
def maximalRectangle(self, matrix: List[List[str]]) -> int:
# 记录当前位置上方连续“1”的个数
pre, ans = [0] * (len(matrix[0]) + 1), 0
for row in matrix:
for j, v in enumerate(row):
pre[j] = (pre[j] + 1) * int(v)
# 把 pre 看成柱子高度同 84 题
q = [-1] # 哨兵
for i, x in enumerate(pre):
while pre[q[-1]] > x:
j = q.pop()
ans = max(ans, pre[j] * (i - q[-1] - 1))
q.append(i)
return ans