84. Largest Rectangle in Histogram (Array, Stack; DP)
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
.
法I: 使用动态规划
class Solution {
public:
int largestRectangleArea(vector<int> &height) {
int* l = new int [height.size()]; //状态:向左连续的>=height[i]的最后一个位置
int* r = new int [height.size()]; //状态:向右连续的>=height[i]的最后一个位置
l[0]=0;
for( int i =1; i <height.size(); i++) //从左往右扫描
{
if(height[i]==0)
{
l[i] = 0;
continue;
}
int j = i-1;
for(; j >= 0; j--){
if(height[i] <= height[j]) j = l[j]; //用动态规划求l[i]否则会Time Limit Exceeded
if(height[i] > height[j]) break;
}
l[i] = j+1;
}
r[height.size()-1]=height.size()-1;
for(int i =height.size()-2; i >=0; i--){ //从右往左扫描
if(height[i]==0)
{
r[i] = 0;
continue;
}
int j = i+1;
for(; j <height.size(); j++){
if(height[i] <= height[j]) j = r[j]; //动态规划
if(height[i] > height[j]) break;
}
r[i] = j-1;
}
int area;
int largestArea = 0;
for(int i = 0; i< height.size(); i++)
{
area = (r[i]-l[i]+1) * height[i];
if(area>largestArea) largestArea = area;
}
return largestArea;
}
};
法I的空间负责度是O(n)+O(n), 为了节省空间,可以用stack代替array来存储最高高度的位置。
法II: stack的栈顶元素表示下一个用来计算面积的高度。
进栈条件:当前元素比栈顶元素大或相等, 进栈后 i++
出栈条件:当前元素比栈顶元素小,出栈后 计算面积 i不变(每个元素都要进一次栈,i要等到比自己小的栈顶元素,然后进栈)
为什么要在此时计算面积?
这个高度到i位置截至了,无法往有再延伸,所以要在当下计算面积。
如何界定计算面积时的左界和右界?
- 左界=新栈顶元素+1
- 右界=当前位置-1
为什么可以这样?
从新栈顶到i的元素高度都>=height[idx],因为如果其中有<height[idx]的元素,那么idx早就出栈了。
空间复杂度最坏情况也只有O(n)
class Solution { public: int largestRectangleArea(vector<int> &height) { if(height.size() == 0) return 0; int res = 0; stack<int> idxStack; height.push_back(0); //为了如果在最后height高于栈顶元素,能够再进一次else,把stack中的元素pop出来计算 int i = 0; int idx; int width; while(i < height.size()) { if(idxStack.empty() || height[i] >= height[idxStack.top()]){ //当前高度>=栈顶高度 idxStack.push(i); //入栈 i++; } else{ //高度降低了 idx = idxStack.top(); idxStack.pop(); //出栈 width = idxStack.empty() ? i : (i-idxStack.top()-1); //界定左右边界 res = max(res, height[idx] * width); //计算面积,并更新最大面积 } } height.pop_back(); return res; } };