分析:假设直方图的左边起点是L,右边起点是R。则如果LR全用的话,则所构成的面积一定是
(
R
−
L
)
∗
H
m
i
n
(R-L)*H_{min}
(R−L)∗Hmin,
H
m
i
n
H_{min}
Hmin表示是LR中最短的
b
a
r
m
i
n
bar_{min}
barmin的高度。而且只要我们使用了
b
a
r
m
i
n
bar_{min}
barmin,所构成的面积一定是小于等于
(
R
−
L
)
∗
H
m
i
n
(R-L)*H_{min}
(R−L)∗Hmin的。那如果我们不用呢?那我们就可以将所有的Bar划分为
[
L
~
b
a
r
m
i
n
)
[L~bar_{min})
[L~barmin)和
(
b
a
r
m
i
n
~
R
]
(bar_{min}~R]
(barmin~R]。同样我们就可以利用递归的思路来处理。
通过上面的分析,我们可以明显的将其转化成一个二分法的问题。
Corn:输入nums, L=0, R=N-1;
找到最短Bar的下标Index
temp1 =
(
R
−
L
+
1
)
∗
H
m
i
n
(R-L+1)*H_{min}
(R−L+1)∗Hmin
temp2 = Corn(nums, Index+1, R);
temp3 = Corn(nums, L, Index-1);
return min(temp1, temp2, temp3);
分析时间复杂度:因为我们二分法里面需要找L到R的最小值,所以我们的时间复杂度还是O(N^2).最坏情况下,如果nums是有序的(increase order),则我们不需要进行二分,通过O(N)的遍历就可以:
r
e
s
=
m
a
x
(
r
e
s
,
h
e
i
g
h
t
[
i
]
∗
(
R
−
i
+
1
)
)
res = max(res, height[i]*(R-i+1))
res=max(res,height[i]∗(R−i+1))。同样decrease order也可以得到相同的结果。
代码:
class Solution {
public:intlargestRectangleAreaBase(const vector<int>& heights,int l,int r){if(l > r)return0;int min_height =-1;int min_height_index = l;
bool increase_sorted = true;
bool decrease_sorted = true;for(int i=l;i<=r;i++){if(min_height ==-1|| min_height > heights[i]){
min_height = heights[i];
min_height_index = i;}if(i != r && heights[i]> heights[i +1]){
increase_sorted = false;}if(i != r && heights[i]< heights[i +1]){
decrease_sorted = false;}}if(increase_sorted){int res =0;for(int i=r;i>=l;i--){
res =max(res, heights[i]*(r-i+1));}return res;}if(decrease_sorted){int res =0;for(int i=l;i<=r;i++){
res =max(res, heights[i]*(i-l+1));}return res;}int res = min_height *(r - l +1);
res =max(res,max(largestRectangleAreaBase(heights, l, min_height_index-1),largestRectangleAreaBase(heights, min_height_index +1, r)));return res;}intlargestRectangleArea(vector<int>& heights){int res =0;int l =0;int r =(int) heights.size()-1;
res =largestRectangleAreaBase(heights, l, r);return res;}staticvoidsolution(){
vector<int> heights ={9,8,7,6,5,4,3,2,1};
Solution solution1;
cout<<solution1.largestRectangleArea(heights)<<endl;}};