求最大面积--------O(n)复杂度

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.

class Solution {
public:
    int Max(int a, int b){return a > b ? a : b;}
    int largestRectangleArea(vector<int> &height) {
        height.push_back(0);
        stack<int> stk;
        int i = 0;
        int maxArea = 0;
        while(i < height.size()){
            if(stk.empty() || height[stk.top()] <= height[i]){
                stk.push(i++);
            }else {
                int t = stk.top();
                stk.pop();
                maxArea = Max(maxArea, height[t] * (stk.empty() ? i : i - stk.top() - 1));
            }
        }
        return maxArea;
    }
};

就用题目中的[2,1,5,6,2,3]来解释一下这段代码吧。

首先,如果栈是空的,那么索引i入栈。那么第一个i=0就进去吧。注意栈内保存的是索引,不是高度。然后i++。

然后继续,当i=1的时候,发现h[i]小于了栈内的元素,于是出栈。(由此可以想到,哦,看来stack里面只存放height单调递增的索引

这时候stack为空,所以面积的计算是h[t] * i。t是刚刚弹出的stack顶元素。也就是蓝色部分的面积。

继续。这时候stack为空了,继续入栈。注意到只要是连续递增的序列,我们都要keep pushing,直到我们遇到了i=4,h[i]=2小于了栈顶的元素。

这时候开始计算矩形面积。首先弹出栈顶元素,t=3。即下图绿色部分。

接下来注意到栈顶的(索引指向的)元素还是大于当前i指向的元素,于是出栈,并继续计算面积,粉色部分。

最后,栈顶的(索引指向的)元素小于了当前i指向的元素,循环继续,入栈并推动i前进。直到我们再次遇到下降的元素,也就是我们最后人为添加的dummy元素0.

同理,我们计算栈内的面积。由于当前i是最小元素,所以所有的栈内元素都要被弹出并参与面积计算。

注意我们在计算面积的时候已经更新过了maxArea。

总结下,我们可以看到,stack中总是保持递增的元素的索引,然后当遇到较小的元素后,依次出栈并计算栈中bar能围成的面积,直到栈中元素小于当前元素。

可以这样理解这个算法,看下图。

例如我们遇到最后遇到一个递减的bar(红色)。高度位于红线上方的(也就是算法中栈里面大于最右bar的)元素,他们是不可能和最右边的较小高度bar围成一个比大于在弹栈过程中的矩形面积了(黄色面积),因为红色的bar对他们来说是一个短板,和红色bar能围成的最大面积也就是红色的高度乘以这些“上流社会”所跨越的索引范围。但是“上流社会”的高度个个都比红色bar大,他们完全只计算彼此之间围成的面积就远远大于和红色bar围成的任意面积了。所以红色bar是不可能参与“上流社会”的bar的围城的。因为虽然长度不占优势,但是团结的力量是无穷的。它还可以参与“比较远的”比它还要屌丝的bar的围城。他们的面积是有可能超过上流社会的面积的,因为距离啊!所以弹栈到比红色bar小就停止了。

另外一个细节需要注意的是,弹栈过程中面积的计算。

h[t] * (stack.empty() ? i : i - stack.top() - 1)

h[t]是刚刚弹出的栈顶端元素。此时的面积计算是h[t]和前面的“上流社会”能围成的最大面积。这时候要注意哦,栈内索引指向的元素都是比h[t]小的,如果h[t]是目前最小的,那么栈内就是空哦。而在目前栈顶元素和h[t]之间(不包括h[t]和栈顶元素),都是大于他们两者的。如下图所示:

那h[t]无疑就是Stack.top()和t之间那些上流社会的短板啦,而它们的跨越就是i - Stack.top() - 1。

所以说,这个弹栈的过程也是维持程序不变量的方法啊:栈内元素一定是要比当前i指向的元素小的。

 

时间: 2024-10-22 03:34:58

求最大面积--------O(n)复杂度的相关文章

hdu 1255 覆盖的面积 线段树扫描线求重叠面积

稀里糊涂打完了没想到1A了,心情还是很舒畅的,c和c++的四舍五入还是四舍六入遇积进位遇偶舍,我感觉很混乱啊,这道题我输出的答案是7.62,也就是遇偶舍了,可是我就手动处理一下进位问题,发现0.005 系统自动进位0.01了,尼玛啊,我一下子就混乱了,不是遇偶舍么,0也是偶数啊,怎么就进位了呢.最后我就不手动处理进位问题了,直接0.2lf%,虽然我输出的结果是7.62,但是提交也过了 这道题和poj1151,hdu1542差不多,扫描线详细讲解http://blog.csdn.net/young

1104: 零起点学算法11——求梯形面积

1104: 零起点学算法11--求梯形面积 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 6473  Accepted: 1875[Submit][Status][Web Board] Description 水题 Input 输入3个浮点数,分别表示上底.下底和高,中间用逗号隔开(题目包含多组数据) Output 输出梯形的面积,保留2位小数 Sample Input 2,4,5 Sample

三角剖分求多边形面积的交 HDU3060

1 //三角剖分求多边形面积的交 HDU3060 2 3 #include <iostream> 4 #include <cstdio> 5 #include <cstring> 6 #include <stack> 7 #include <queue> 8 #include <cmath> 9 #include <algorithm> 10 using namespace std; 11 12 const int max

25.按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有

package zhongqiuzuoye; public class Rect { public double width; public double height; Rect(double width,double height) //带有两个参数的构造方法,用于将width和height属性初化; { this.width=width; this.height=height; } Rect() //不带参数的构造方法,将矩形初始化为宽和高都为10. { width=10; height=

HDU 1542 Atlantis (求矩形面积并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of

HDU 1255 覆盖的面积 (求矩形面积的交)

覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Description 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个

poj1408——叉积求多边形面积

poj1408——叉积求多边形面积 Fishnet Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1853   Accepted: 1185 Description A fisherman named Etadokah awoke in a very small island. He could see calm, beautiful and blue sea around the island. The previou

POJ 2540 半平面交求可行区域面积

Hotter Colder Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2343   Accepted: 981 Description The children's game Hotter Colder is played as follows. Player A leaves the room while player B hides an object somewhere in the room. Player

UVA - 11983 Weird Advertisement (线段树求并面积)

Description G Weird Advertisement Renat Mullakhanov (rem), one of the most talented programmers in the world, passed away on March 11, 2011. This is very sad news for all of us. His team went to ACM ICPC World Finals - 2004, placed 4th and won gold m