最大直方图面积
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.
最简单的思路就是遍历每个值,当遍历到一个值的时候就开始向两边扩张,如上图的例子
数组为{2,1,5,6,2,3} 以1位置为例 :他可以向左扩张到-1位置(不包括-1)
也可以向右扩张到array.size()位置
假设他向右扩张的位置是n 想左扩张的位置是 j,当前位置为i
那么以i高度为宽的矩形最大面就是(j-n-1)*array[i];
同理依次遍历计算其它位置 获取最大面积即可
常规解法时间复杂度为O(n*n) 空间复杂度为O(1)
int largestRectangleArea(vector<int> &height)
{
// write your code here
if(height.empty())
return 0;
int res=0;
for(int i=0;i<height.size();i++)
{
int n=i;
int j=i;
while(n >= 0 && height[n] >= height[i])
{
n--;
}
while(j < height.size() && height[j] >= height[i])
{
j++;
}
int cur=(j-n-1)*height[i];
res=res>cur?res:cur;
}
return res;
}
要降低时间复杂度需要使用栈来保存当前位置能向左和右扩张的位置先开始遍历数组数据,栈为空的时候以及栈顶数据小于当前数组数据
就把当前数组下标加入到栈中,保证了栈是一个单调递增且无重复的栈
如果有一个数据小于栈顶数据,则将栈顶数据逐次弹出知道栈顶数据大于
当前数组数据保证栈的单调递增性质 。。。在逐次弹出的过程中 我们可以
计算出以栈顶位置为中心向左右扩散的最大值,因为栈是逐次递增的使用,栈顶数据
不能向左扩张 所以假设栈顶数据是 j 栈顶后面的数据是n 当前数组数据下标是i
弹出栈顶j后 以j位置为中心的扩张范围就是(j-n-1)如果弹出j后栈为空那么n视为-1
原因就是说 既然array[i]<array[j]所以j自然是不能向右扩张的,而栈又是一个递增栈
所以也不能向栈底扩张。
当数组数据最后一个数据也入栈了 说明栈内的数据都能向右扩张到最远
只需要获取栈能向左扩张的距离
同理此时的范围就是(array.size()-n-1);
在上述分析中 数据只入栈了一次并且也只出栈了一次,所以时间复杂度是在线性范围之内
O(n)代码如下
int largestRectangleArea(vector<int> &height)
{
// write your code here
if(height.empty())
return 0;
int res=0;
stack<int > index;
for(int i=0;i<height.size();i++)
{
while(!index.empty()&&height[i]<=height[index.top()])
{
int j=index.top();
index.pop();
int n= index.empty()?-1:index.top();
int cur=(i-n-1)*height[j];
res=res>cur?res:cur;
}
index.push(i);
}
while(!index.empty())
{
int j=index.top();
index.pop();
int n= index.empty()?-1:index.top();
int cur=(height.size()-n-1)*height[j];
res=res>cur?res:cur;
}
return res;
}
问题二
给你一个二维矩阵,权值为False
和True
,找到一个最大的矩形,使得里面的值全部为True
,输出它的面积
给你一个矩阵如下
[
[1, 1, 0, 0, 1],
[0, 1, 0, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 1]
]
输出6
设定一个dp数组 代表着 以第i行为底边 dp[j]该条位置往下连续为真的个数
如果矩阵rangle[i][j]=0 dp[j]不能代表他的底
上图的矩阵可以产生5组dp数组
分别为
1 1 0 0 1
0 2 0 0 2
0 0 1 1 3
0 0 2 2 4
0 0 0 0 1
那最大矩阵数不就是每个dp数组的最大直方图面积?
所以有了上到题的代码我们可以轻松实现该问题的解
int maximalRectangle(vector<vector<bool> > &matrix)
{
// Write your code here
if(matrix.empty())
return 0;
vector<int > height(matrix[0].size(),0);
int res=0;
for(int i=0;i<matrix[0].size();i++)
if(matrix[0][i]==1)
{
height[i]=1;
res=1;
}
for(int i=1;i<matrix.size();i++)
{
for(int j=0;j<matrix[0].size();j++)
{
if(matrix[i][j]==1)
height[j]+=1;
else
height[j]=0;
}
int cur=largestRectangleArea(height);
res=res>cur?res:cur;
}
return res;
}
int largestRectangleArea(vector<int> height)
{
// write your code here
if(height.empty())
return 0;
int res=0;
std::stack<int > staRes;
for(int i=0;i<height.size();i++)
{
while(!staRes.empty()&&height[i]<=height[staRes.top()])
{
int j=staRes.top();
staRes.pop();
int k=staRes.empty()?-1:staRes.top();
int cur=(i-k-1)*height[j];
res=res>cur?res:cur;
}
staRes.push(i);
}
while(!staRes.empty())
{
int j=staRes.top();
staRes.pop();
int k=staRes.empty()?-1:staRes.top();
int cur=(height.size()-k-1)*height[j];
res=res>cur?res:cur;
}
return res;
}