题目:
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.
题目大意就是给出一个柱状图的高度的数组,求出其中能画出的最大矩形的面积。
1.方法一
一个比较简单暴力,容易理解的方法:对于每一个方柱,分别向左向右遍历,到达第一个小于该方柱高度的方柱停止,此时画出了一个以该方柱为最小高度的最大矩形,可以计算出面积:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
if (heights.empty())
return 0;
int max = 0;
for (int i = 0; i < heights.size(); ++i) {
if (heights[i] <= max/heights.size()) continue;//如果该方柱高度过低,那也没有计算的必要了,略过
int temp = helper(heights, i);
if (temp > max)
max = temp;
}
return max;
}
private:
int helper(const vector<int>& heights, int i) {
if (heights[i] == 0) return 0;
int l = i, r = i;
while(l-1 >= 0 && heights[l-1] >= heights[i]) --l;
while(r+1 < heights.size() && heights[r+1] >= heights[i]) ++r;
return heights[i] * (r-l+1);
}
};
2.方法二
解法来源:https://www.geeksforgeeks.org/largest-rectangle-under-histogram/
比较难以理解,但是该方法时间复杂度为O(N),值得思考。
方法是这样的:还是要找出以每个方柱为最低高度的最大矩形,关键就是找出左边第一个小于该高度的和右边第一个小于该高度的。维持一个stack,遍历输入的数组。如果当前遍历的该方柱高度大于等于栈顶的方柱高度,那么就将其压入栈;如果当前遍历的该方柱高度小于栈顶的方柱高度,就一直将栈顶元素弹出,直到该方柱高度大于等于栈顶的方柱高度。对于每个弹出的方柱,计算以它为最低高度的最大矩形的面积,计算的方法:弹出后当前栈顶的方柱是左边第一个小于该高度的方柱,当前遍历的方柱是右边第一个小于该高度的方柱。
这是从左往右遍历的。实际编程中,为了方便,往往在右边放一个高度为0的方柱作为哨兵,然后从右往左遍历。
光看文字描述比较难以理解,需要自己在草稿纸上举一个例子,将整个过程模拟一遍,好好体会一下。
下面是我的代码:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
if (heights.empty())
return 0;
int max = 0;
heights.push_back(0);//作为哨兵
int N = heights.size();
stack<int> si;
si.push(N-1);
for (int i = N-2; i >= 0; --i) {
if (heights[i] >= heights[si.top()]) {
si.push(i);
continue;
}
while (heights[si.top()] > heights[i]) {
int t = si.top();
si.pop();
int s = heights[t] * (si.top()-i-1);
if (s > max)
max = s;
}
si.push(i);
}
while (si.size() > 1) {//遍历结束后,将栈里面残留的元素弹出
int t = si.top();
si.pop();
int s = heights[t] * (si.top()-(-1)-1);
if (s > max)
max = s;
}
return max;
}
};