您的位置:首页 > 其它

LeetCode_Largest Rectangle in Histogram

2014-09-30 16:40 267 查看
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]
.



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
.

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
.

题目要求求出矩形图的最大面积,数组给出每个条形图的高度,条形图的默认宽度为1.

1、最基本的解法:

枚举矩形的起点和终点,时间复杂度O(n^2),空间复杂度O(1).提交,果断超时。

class Solution {
public:
int largestRectangleArea(vector<int> &height) {
if(height.size() == 0) return 0;

int maxSquare = 0;
int smallest = height[0];

for(int beg=0; beg<height.size(); beg++){
smallest = height[beg];
for(int end=beg+1; end<height.size(); end++){
if(height[end]<smallest){
smallest = height[end];
}
int curSquare = smallest*(end-beg);
if(curSquare>maxSquare){
maxSquare = curSquare;
}
}
}

return maxSquare;
}
};


2、分治法

换个思路来想,对于给定的高度数组height[l..r],其矩形面积的求解公式为:

square = min(height[l..r])*(r-l)
题目要求求出对应数组的可能的最大矩形面积,我们记:
minPos = {pos | l <= pos <= r, height[pos] = min(height[l..r])}
则对应区段heigth[l..r]的可能最大面积取值来源于:
1) square = min(height[l..r])*(r-l)
2) square of height[l..minPos-1]
3) square of height[minPos+1..r]
由此对于任何区间height[l..r]我们需要O(n)的线性时间复杂度来找到对应区间中的最小高度位置minPos,同时将原问题分为两个相互独立的子问题,由此整个问题的求解平均时间复杂度为O(nlogn),空间复杂度为O(1),提交,依然超时。
class Solution {
public:
int largestRectangleArea(vector<int> &height) {
if(height.size() == 0) return 0;

int maxSquare = 0;

calculateRangeArea(height,0,height.size()-1,maxSquare);

return maxSquare;
}
private:
void calculateRangeArea(vector<int> &height, int l, int r, int &square){
if(l>r) return;
int smallest = height[l];
int pos = l;
for(int i=l+1;i<r;i++){
if(height[i]<smallest){
smallest = height[i];
l = i;
}
}
int curSquare = (r-l)*smallest;
if(curSquare>square){
square = curSquare;
}

calculateRangeArea(height, l, pos-1, square);
calculateRangeArea(height, pos+1, r, square);
}
};


3.O(n)线性时间复杂度的解法
问题要求出给定高度数组height[0,..,n-1]的最大矩形面积,如果我们求出了一任何一个以height[i](0 <= i <= n-1)为最小高度所构成的矩形面积,那我们就一定可以从中选出最大的矩形面积,问题也就解决了。
那么对于数组中任意一个位置pos,我们如何计算以height[pos]为最小高度的矩形面积呢?我们需要知道两个条件:a) pos左侧的第一个小于height[pos]的位置,记为left;b) pos右侧的第一个大于height[pos]的位置,记为right。

那么如何知道right和left呢?我们使用一个栈s存储height数组中的高度下标,栈中的元素满足:越靠近栈顶的元素的高度越高。
从左向右遍历数组height,存在如下两种情况:
a) 如果当前便利位置i满足height[i]>height[s.top]那么将i入栈,
b)否则我们相当于找到了s.top右侧的第一个小于height[s.top]的位置right=i;这时执行弹栈操作,tp=s.top,s.pop,还需要解决的问题就是如何得到左侧第一个小于height[tp]的位置呢,其实我们所构造的栈s的特性已经解决了这个问题,弹栈操作执行完毕后的s.top就是左侧第一个小于height[tp]的位置left,这样以height[tp]为最小高度的面积就可以求解出来了;
如果数组遍历一遍完成后,栈s不空,这时,站内元素的right边界为right = n-1,left元素的边界仍按照b)中的方式计算就可以了。
真个算法时间复杂度为O(n),空间复杂O(n).
class Solution {
public:
int largestRectangleArea(vector<int> &height) {
if(height.size()==0){
return 0;
}

//Create an empty stack. The stack holds indexes of
//vector <int> height.
//The bars stored in stack are always in increasing order
//of their heights
stack <int> s;

int max_area = 0; //Initialize max area
int tp; //To store top of stack
int area_with_top; //to store area with top bar as the smallest bar

//Run through all bars of given histogram
int i = 0;

while(i < n){
//If this bar is higher than the bar on the stack, push it to stack
if(s.empty() || height[s.top()] <= height[i]){
s.push(i++);
}

//If this bar is lower than top of stack, then calculate area
//with stack top as the smallest (or mimimum height) bar. 'i' is
//'right index' for the top and element before top in stack is
//'left index'
else {
tp = s.top(); //store the top index
s.pop(); //pop the top

//Calculate the area with height[tp] stack as smallest bar
area_with_top = height[tp]*(s.empty?i:i-s.top()-1);

//update max area, if needed
if(max_area < area_with_top){
max_area = area_with_top;
}
}
}

//Now pop the remaining bars from stack and calculate area with
//elements popped bar as the smallest bar
while(s.empty() == false){
tp = s.top();
s.pop();
area_with_top = height[tp]*(s.empty()?i:i-s.top()-1);
if(max_area<area_with_top){
max_area = area_with_top;
}
}

return max_area;
}
};


Reference:
http://www.geeksforgeeks.org/largest-rectangle-under-histogram/

http://www.geeksforgeeks.org/largest-rectangular-area-in-a-histogram-set-1/

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: