思路:
方法一:TLE。时间复杂度O(N^2),空间复杂度O(1)。
对于每一个柱子,往左右两边扩展,不断更新最大的area。
往右扩展:如果右边柱子比当前柱子高,则往右扩。相当于剪枝。
往左扩展:找到目前为止最低的柱子,以此来构成矩形。
class Solution {
public:
int largestRectangleArea(vector<int>& height) {
int ans = 0;
for(int i = 0; i < height.size(); ++i) {
//prune : find the max i by current i
for(int k = i + 1; k < height.size(); ++k) {
if(height[k-1] < height[k]) {
i = k;
}else {
i = k - 1;
break;
}
}
//calculate from i to far left
int lowest = height[i];
for(int j = i; j >= 0; --j) {
if(height[j] < lowest) {
lowest = height[j];
}
int current_area = (i - j + 1) * lowest;
ans = current_area > ans ? current_area : ans;
}
}
return ans;
}
};
方法二:通过栈来控制。时间复杂度O(N),空间复杂度O(N)。
算法思路非常巧妙,以给定的数据集[2,1,5,6,2,3]为例:
如果栈为空 或者 当前柱子高度大于栈顶柱子高度,则当前柱子索引入栈;
否则,从栈顶不断弹出索引,不断的计算可能的矩形面积。预先往height数组尾端放入一个 0
,保证会计算最后的height。
当 i = 0
时,栈为空,把第0号柱子压栈;
当 i = 1
时,第1号柱子高度1小于栈顶柱子高度2,出栈并计算面积;
栈空,第1号柱子入栈;
当 i = 2
时,第2号柱子高度5大于栈顶柱子高度1,入栈;
当 i = 3
时,第6号柱子高度6大于栈顶柱子高度5,入栈;
可以看出,栈中的所在索引的柱子高度一定是递增的;
当 i = 4
时,第4号柱子高度2小于栈顶柱子高度6,出栈并计算面积;
第4号柱子高度2继续小于栈顶柱子高度5,出栈并计算面积;
第4号柱子高度2大于栈顶柱子高度1,第4号柱子入栈;
当 i = 5
时,第5号柱子高度3大于栈顶柱子高度2,入栈;
这时轮到了提前放入height数组中的 0
:
第6号柱子高度0小于栈顶柱子高度3,出栈并计算面积;
第6号柱子高度0小于栈顶柱子高度2,出栈并计算面积;
第6号柱子高度0小于栈顶柱子高度1,出栈并计算面积;
之后,第0号柱子入栈,for循环条件不满足退出。
返回所有得到面积的最大值,over。
class Solution {
public:
int largestRectangleArea(vector<int>& height) {
stack<int> s;
height.push_back(0);
int ans = 0;
for(int i = 0; i < height.size();) {
if(s.empty() || height[i] > height[s.top()]) {
s.push(i);
++i;
}else {
int tmp = s.top();
s.pop();
ans = max(ans, height[tmp] * (s.empty() ? i : i - s.top() - 1));
}
}
return ans;
}
};