直方图最大矩形覆盖
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.
分析一下可以发现,在直方图的某一位置i,对于其左边任何不低于height[i]的bar的高度height[j],并不会对该位置所构成的最大矩形产生影响。如题目样例[2,1,5,6,2,3]中,对于位置i=1,无论样例是[2,1,5,6,2,3]、[1,1,5,6,2,3]还是[5,1,5,6,2,3]都不会影响i=1是的最大矩形面积max=2。
因此只要保存从开始到i-1位置的高度递增序列,在位置i更新最大矩形max。比较i位置的bar与序列最后元素的高度:
当bar.y>h.back().y时,将bar直接加入序列h;
而bar.y<=h.back().y时,丢弃先前序列中高度小于bar的元素。
注意删除时忘了j–会跳过一个元素
class Solution {
public:
/**
* @param height: A list of integer
* @return: The area of largest rectangle in the histogram
*/
struct increase{
int x,y;
};
int largestRectangleArea(vector<int> &height) {
// write your code here
vector<increase> h(1);
h[0].x=-1;
h[0].y=0;
int max=0;
for(int i=0;i<height.size();i++)
{
increase t;
t.x=i;
t.y=height[i];
for(int j=0;j<h.size();j++)
{
auto s=(i-h[j-1].x)*min(h[j].y,t.y);
if(s>max)
{
max=s;
}
if(h[j].y>=t.y)
{
//delete
h.erase(h.begin()+j);
j--;
}
}
h.push_back(t);
auto s=(i-h[h.size()-2].x)*t.y;
max=s>max?s:max;
}
return max;
}
};
结果超时了,可以看出并不是所有位置都需要计算max。新增的bar是不需要计算max的,因为后面的bar高度可能高于该bar,因此,在删除元素时进行最大矩形的计算可以节省时间。
另一方面,只有增加了只有处于高度递增序列最大值的元素才需要计算并更新最大矩形max,而其之前的最大矩形必定小于该位置的最大矩形。因此加入max_x记录当前计算过的最大矩阵的下标位置,当删除元素时,只有当前下标大于max_x的位置才进行计算。
在序列前后分别加入高度为-1,0的元素以省去判断过程。两个高度不能一样,否则就会变成成未递增的序列而被删除。
class Solution {
public:
/**
* @param height: A list of integer
* @return: The area of largest rectangle in the histogram
*/
struct increase{
int x,y;
};
int largestRectangleArea(vector<int> &height) {
// write your code here
vector<increase> h(1);
h[0].x=-1;
h[0].y=-1;
//在序列前加入-1
height.push_back(0);
//在序列后加入0
int max=0;
//当前最大矩形面积
int max_x=-1;
//当前比较过最大矩形的最后下标,注意不能设成0,否则从第二个元素开始算
for(int i=0;i<height.size();i++)
{
increase t;
t.x=i;
t.y=height[i];
while(t.y<=h.back().y)//未递增
{
if(h.back().x>max_x)
{
for(int j=1;j<h.size();j++)
{
auto s=(h.back().x-h[j-1].x)*h[j].y;
if(s>max)
{
max=s;
}
}
max_x=h.back().x;
}
h.pop_back();
}
h.push_back(t);
}
return max;
}
};