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) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int size = height.size();
int max = 0 ;
int current = 0 ; //存放的是包含height[i]全部的矩形的面积
for ( int i = 0 ;i < size;i ++ )
{
if (height[i] == 0 )
continue ;
current = height[i];
int left = i - 1 ;
int right = i + 1 ;
while (left > = 0 && height[left -- ] > = height[i])current += height[i];
while (right < size && height[right ++ ] > = height[i])current += height[i];
if (current > max)
max = current;
}
return max;
}
};
public :
int largestRectangleArea(vector < int > & height) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int size = height.size();
int max = 0 ;
int current = 0 ; //存放的是包含height[i]全部的矩形的面积
for ( int i = 0 ;i < size;i ++ )
{
if (height[i] == 0 )
continue ;
current = height[i];
int left = i - 1 ;
int right = i + 1 ;
while (left > = 0 && height[left -- ] > = height[i])current += height[i];
while (right < size && height[right ++ ] > = height[i])current += height[i];
if (current > max)
max = current;
}
return max;
}
};
上面的结果之所以超时的原因是由于有重复的计算。
比如下面图示:

当计算到3时的时候,会向左查找到2.这里面就包含了重复的问题。
因为3的左面的4比他大。所以4
能到达的左边界,一定会大于等于3能到达的,所以可以直接从4能到达的左边界开始向左遍历就行了,不用遍历4和5这段区间了。
5
5 4
5 4 3
2 5 4 3
1 2 5 4 3
这时经过一次从左向右的遍历i可以求得每个木桩的左边界。
同理经过一次从右向左的遍历i可以求得每个木桩的右边界。
note:
此题在做的时候,本来已经想到了这个可以优化的部分,但是当时只想着一次从左到右的遍历,这样就无法优化右边界的求解。后来经过提示,才发现,一个木桩的左右边界互不影响,所以可以分2次遍历,分别求出左右边界,然后再遍历木桩计算面积。
此题提示,有2个子问题的时候,不要老是和以前的dp一样,只遍历一次。有几个子问题,要遍历求解几次。
class Solution {
public :
int largestRectangleArea(vector < int > &height) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int size =height.size();
int max = 0;
vector < int >left(size, 0); //存放的height[i]左面和他相连的大于等于他的最左的位置
vector < int >right(size,size - 1); //存放的height[i]右面和他相连的大于等于他的最右的位置
for( int i = 0;i <size;i ++)
{
if(i==0||height[i]>height[i-1])
left[i]=i;
else
for(int j=left[i-1];j>=0;j--)
if(height[j]>=height[i])
{
left[i]=j
;//此处可以优化
/*
left[i]=left[j];
j=left[j];
*/
}
else
break;
}
for(int i=size-1;i>=0;i--)
{
if(i==size-1||height[i]>height[i+1])
right[i]=i;
else
for(int j=right[i+1];j<=size-1;j++)
if(height[j]>=height[i])
{
right[i]=j;
;//此处可以优化
/*
right[i]= right[j];
j= right[j];
*/
}
else
break;
}
for(
int
i
=
0;i
<size;i
++)
max =max >(right[i] -left[i] + 1) *height[i] ?max :(right[i] -left[i] + 1) *height[i];
return max;
}
};