怎么用C++求直方图中最大的矩形(C++,编程语言)

时间:2024-04-28 04:19:32 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

直方图中最大的矩形

Givennnon-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.

怎么用C++求直方图中最大的矩形

Above is a histogram where width of each bar is 1, given height =[2,1,5,6,2,3].

怎么用C++求直方图中最大的矩形

The largest rectangle is shown in the shaded area, which has area =10unit.

For example,
Given height =[2,1,5,6,2,3],
return10.

这道题让求直方图中最大的矩形,刚开始看到求极值问题以为要用DP来做,可是想不出递推式,只得作罢。这道题如果用暴力搜索法估计肯定没法通过OJ,有一种很好的优化方法,就是遍历数组,每找到一个局部峰值(只要当前的数字大于后面的一个数字,那么当前数字就看作一个局部峰值,跟前面的数字大小无关),然后向前遍历所有的值,算出共同的矩形面积,每次对比保留最大值。这里再说下为啥要从局部峰值处理,看题目中的例子,局部峰值为 2,6,3,我们只需在这些局部峰值出进行处理,为啥不用在非局部峰值处统计呢,这是因为非局部峰值处的情况,后面的局部峰值都可以包括,比如1和5,由于局部峰值6是高于1和5的,所有1和5能组成的矩形,到6这里都能组成,并且还可以加上6本身的一部分组成更大的矩形,那么就不用费力气去再统计一个1和5处能组成的矩形了。代码如下:

解法一:

//Pruningoptimize
classSolution{
public:
intlargestRectangleArea(vector<int>&height){
intres=0;
for(inti=0;i<height.size();++i){
if(i+1<height.size()&&height[i]<=height[i+1]){
continue;
}
intminH=height[i];
for(intj=i;j>=0;--j){
minH=min(minH,height[j]);
intarea=minH(i-j+1);
res=max(res,area);
}
}
returnres;
}
};

后来又在网上发现一种比较流行的解法,是利用栈来解,可参考其他文档,但是经过仔细研究,其核心思想跟上面那种剪枝的方法有异曲同工之妙,这里维护一个栈,用来保存递增序列,相当于上面那种方法的找局部峰值。我们可以看到,直方图矩形面积要最大的话,需要尽可能的使得连续的矩形多,并且最低一块的高度要高。有点像木桶原理一样,总是最低的那块板子决定桶的装水量。那么既然需要用单调栈来做,首先要考虑到底用递增栈,还是用递减栈来做。我们想啊,递增栈是维护递增的顺序,当遇到小于栈顶元素的数就开始处理,而递减栈正好相反,维护递减的顺序,当遇到大于栈顶元素的数开始处理。那么根据这道题的特点,我们需要按从高板子到低板子的顺序处理,先处理最高的板子,宽度为1,然后再处理旁边矮一些的板子,此时长度为2,因为之前的高板子可组成矮板子的矩形 ,因此我们需要一个递增栈,当遇到大的数字直接进栈,而当遇到小于栈顶元素的数字时,就要取出栈顶元素进行处理了,那取出的顺序就是从高板子到矮板子了,于是乎遇到的较小的数字只是一个触发,表示现在需要开始计算矩形面积了,为了使得最后一块板子也被处理,这里用了个小 trick,在高度数组最后面加上一个0,这样原先的最后一个板子也可以被处理了。由于栈顶元素是矩形的高度,那么关键就是求出来宽度,那么跟之前那道Trapping Rain Water一样,单调栈中不能放高度,而是需要放坐标。由于我们先取出栈中最高的板子,那么就可以先算出长度为1的矩形面积了,然后再取下一个板子,此时根据矮板子的高度算长度为2的矩形面积,以此类推,知道数字大于栈顶元素为止,再次进栈,巧妙的一比!关于单调栈问题可以参见博主的一篇总结帖LeetCode Monotonous Stack Summary 单调栈小结,代码如下:

解法二:

classSolution{
public:
intlargestRectangleArea(vector<int>&height){
intres=0;
stack<int>st;
height.push_back(0);
for(inti=0;i<height.size();++i){
if(st.empty()||height[st.top()]<height[i]){
st.push(i);
}else{
intcur=st.top();st.pop();
res=max(res,height[cur]
(st.empty()?i:(i-st.top()-1)));
--i;
}
}
returnres;
}
};

我们可以将上面的方法稍作修改,使其更加简洁一些:

解法三:

classSolution{
public:
intlargestRectangleArea(vector<int>&heights){
intres=0;
stack<int>st;
heights.push_back(0);
for(inti=0;i<heights.size();++i){
while(!st.empty()&&heights[st.top()]>=heights[i]){
intcur=st.top();st.pop();
res=max(res,heights[cur]*(st.empty()?i:(i-st.top()-1)));
}
st.push(i);
}
returnres;
}
};

本文:怎么用C++求直方图中最大的矩形的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:C++跳跃游戏问题怎么解决下一篇:

7 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18