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.
For example,
Given height = [2,1,5,6,2,3]
,
return 10
.
思路:
对于每一个点都尝试找出以它为高的最大矩形。
更直白地说,就是往左右两侧尽可能地拓展。
例如: 2 1 3 4 5
对height[2]=3而言,左侧最多就是自己,右侧可以到5。
程序语言描述就是:
height[i] <= height[j], L[i] = min{j}
height[i] <= height[k], R[i] = max{k}
简单暴力的方法:直接遍历
for (int i = 0; i < n; i++) {
l[i] = 0;
r[i] = n - 1;
for (int j = i - 1; j >= 0; j--) {
if (height[j] < height[i]) {
l[i] = j + 1;
break;
}
}
for (int j = i + 1; j < n; j++) {
if (height[j] < height[i]) {
r[i] = j - 1;
break;
}
}
if ((r[i] - l[i] + 1) * height[i] > max) {
max = (r[i] - l[i] + 1) * height[i]
}
}
再仔细想想哪些地方做了重复的工作。
以 2 1 3 4 5为例,
我们已经知道R[2] = 4 (height[2] = 3),对于R[1] (height[1] = 1),由于height[1] <= height[2],因此没必要再遍历2到R[2]这一段,即3 4 5,。
因为height[i] <= height[i + 1] <= ... <= height[R[i]],
因此如果height[i - 1] <= height[i],则R[i - 1] >= R[i],所以我们可以直接比较height[i - 1]与height[R[i] + 1],直到找到height[i - 1] > height[R[j] + 1]。
class Solution {
public:
int largestRectangleArea(vector<int> &height) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int n = height.size();
int l[n], r[n];
memset(l, 0, sizeof(int) * n);
memset(r, 0, sizeof(int) * n);
l[0] = 0;
for (int i = 1; i < n; i++) {
if (height[i] > height[i - 1]) {
l[i] = i;
}
else {
int idx = l[i - 1];
while (idx > 0 && height[i] <= height[idx - 1]) {
idx = l[idx - 1];
}
l[i] = idx;
}
}
r[n - 1] = n - 1;
for (int i = n - 2; i >= 0; i--) {
if (height[i] > height[i + 1]) {
r[i] = i;
}
else {
int idx = r[i + 1];
while (idx < n - 1 && height[i] <= height[idx + 1]) {
idx = r[idx + 1];
}
r[i] = idx;
}
}
int max = 0;
for (int i = 0; i < n; i++) {
if ((r[i] - l[i] + 1) * height[i] > max) {
max = (r[i] - l[i] + 1) * height[i];
}
}
return max;
}
};
public class Solution {
public int largestRectangleArea(int[] height) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if (height == null || height.length == 0) {
return 0;
}
int[] left = new int[height.length];
int[] right = new int[height.length];
for (int i = 1; i < height.length; i++) {
int k = i;
while (k > 0 && height[k - 1] >= height[i]) {
k = left[k - 1];
}
left[i] = k;
}
right[height.length - 1] = height.length - 1;
for (int i = height.length - 2; i >= 0; i--) {
int k = i;
while (k < height.length - 1 && height[k + 1] >= height[i]) {
k = right[k + 1];
}
right[i] = k;
}
int max = 0;
for (int i = 0; i < height.length; i++) {
max = max > height[i] * (right[i] - left[i] + 1) ? max : height[i] * (right[i] - left[i] + 1);
}
return max;
}
}