[LeetCode] 84. Largest Rectangle in Histogram(直方图里的最大矩形)
- Difficulty: Hard
- Related Topics: Array, Stack
- Link: https://leetcode.com/problems/largest-rectangle-in-histogram/
Description
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.
给定 n 各非负整数,表示直方图中每个柱子的高度(所有柱子的宽度都是 1),找到该立方图中面积最大的矩形的面积。
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]
.
上图中,每个柱子的高度是 1,高度为 [2, 1, 5, 6, 2, 3]
。
The largest rectangle is shown in the shaded area, which has area = 10
unit.
上图中面积最大的矩形为阴影所示,面积为 10 个单位。
Example
Input: [2,1,5,6,2,3]
Output: 10
Solution
对于每一个 heights[i]
,其最大的矩形面积为以 heights[i]
为高的矩形,也就是说,包含 heights[i]
的矩形范围内不能有比 height[i]
还矮的柱子。于是我们就需要知道每个柱子左右两边第一个比该柱子矮的柱子。常规方法需要 \(O(N^2)\) 时间找到所有柱子的左右两边第一个比该柱子矮的柱子。但实际上可以利用已经计算的结果。以找 heights[i]
左边第一个比它矮的柱子为例,如果 heights[i - 1]
比 heights[i]
更高,那么第一个比 heights[i]
矮的柱子肯定也是比 heights[i - 1]
矮的柱子。找右边的柱子同理。代码如下:
import kotlin.math.max
class Solution {
fun largestRectangleArea(heights: IntArray): Int {
if (heights.isEmpty()) {
return 0
}
val lessFromLeft = IntArray(heights.size)
val lessFromRight = IntArray(heights.size)
lessFromLeft[0] = -1
lessFromRight[lessFromRight.lastIndex] = heights.size
for (i in 1..heights.lastIndex) {
var p = i - 1
while (p >= 0 && heights[p] >= heights[i]) {
p = lessFromLeft[p]
}
lessFromLeft[i] = p
}
for (i in (heights.lastIndex - 1) downTo 0) {
var p = i + 1
while (p < heights.size && heights[p] >= heights[i]) {
p = lessFromRight[p]
}
lessFromRight[i] = p
}
var result = 0
for (i in heights.indices) {
result = max(result, heights[i] * (lessFromRight[i] - lessFromLeft[i] - 1))
}
return result
}
}