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.

O(n^2):

Judge Small: Accepted!
Judge Large: Time Limit Exceeded

int largestRectangleArea(vector<int> &height) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int end = height.size();
int begin = 0;
int largestarea = 0;
for(int i = begin; i < end; ++i)
{
int area;
int high = height[i];
for(int j = i; j < end; ++j){
if(height[j] < high) high = height[j];
area = (j - i + 1)*high;
if(area > largestarea) largestarea = area;
}
}
return largestarea;
}

O(n):

Judge Small: Accepted!
Judge Large:Accepted!

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指向的元素小的。

leetcode_question_85 Largest Rectangle in Histogram的更多相关文章

  1. LeetCode 笔记系列 17 Largest Rectangle in Histogram

    题目: Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar he ...

  2. 47. Largest Rectangle in Histogram && Maximal Rectangle

    Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar height ...

  3. 【LeetCode】84. Largest Rectangle in Histogram

    Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar height ...

  4. leetcode Largest Rectangle in Histogram 单调栈

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4052343.html 题目链接 leetcode Largest Rectangle in ...

  5. 关于LeetCode的Largest Rectangle in Histogram的低级解法

    在某篇博客见到的Largest Rectangle in Histogram的题目,感觉蛮好玩的,于是想呀想呀,怎么求解呢? 还是先把题目贴上来吧 题目写的很直观,就是找直方图的最大矩形面积,不知道是 ...

  6. leetcode之Largest Rectangle in Histogram

    问题来源:Largest Rectangle in Histogram 问题描述:给定一个长度为n的直方图,我们可以在直方图高低不同的长方形之间画一个更大的长方形,求该长方形的最大面积.例如,给定下述 ...

  7. LeetCode之“动态规划”:Maximal Square && Largest Rectangle in Histogram && Maximal Rectangle

    1. Maximal Square 题目链接 题目要求: Given a 2D binary matrix filled with 0's and 1's, find the largest squa ...

  8. 84. Largest Rectangle in Histogram

    https://www.cnblogs.com/grandyang/p/4322653.html 1.存储一个单调递增的栈 2.如果你不加一个0进去,[1]这种情况就会输出结果0,而不是1 3.单调递 ...

  9. LeetCode: Largest Rectangle in Histogram 解题报告

    Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar height ...

随机推荐

  1. PNPOLY - Point Inclusion in Polygon W. Randolph Franklin

    测试目标点是否在多边形内int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy) { int i, j, ...

  2. JNDI support differences between Tibco EMS and ActiveMQ

    Introduction Recently our team was working on Veracity Quick Start sprint, when I was trying to migr ...

  3. 限制TextBox输入,只能输入Double类型数字

    public class TextBoxDouble : TextBox { public TextBoxDouble() { KeyDown += TextBoxDouble_KeyDown; Te ...

  4. ubuntu_安装aptana3

    下面记录下偶怎么安装aptana3(aptana2应该也适用). 安装java运行时,偷看这里 说明:实际上偶并没有执行这步,因为发现在安装aptana3之前 java的运行时已经安装过了. 貌似是安 ...

  5. 常见 wifi热点的linux 驱动

    小度Wifi.360Wifi Windows.linux驱动 小度wifi什么的就是一个无线网卡,当然可以自由使用,然官方却说不支持无限网卡功能… 现提供Windows平台和linux平台的驱动安装方 ...

  6. ar解压deb包

    解压文件 ar -x libstdc++6_4.7.2-5_i386.deb tar -zxvf data.tar.gz

  7. AU3学习笔记

    目录 1. AU3是什么?能做什么? 2. 乱学AU3中的命令(语言相关)? 3. 通过简单示例学习AU3? 4. 正则表达式的学习(对大小写敏感) 5.对于GUI的相关学习 1.        AU ...

  8. C#中dynamic的正确用法【转】

    dynamic是FrameWork4.0的新特性.dynamic的出现让C#具有了弱语言类型的特性.编译器在编译的时候不再对类型进行检查,编译期默认dynamic对象支持你想要的任何特性.比如,即使你 ...

  9. Java复习第一天---Javascript的基本知识点

    1.HelloWord: 2.基础语法: 3.嵌入HTML 借助window.onload事件在整个窗体载入完毕之后运行程序代码 4.事件驱动: 5.DOM操作 5.1 查找元素节点 5.1.1 依据 ...

  10. 两种Makefile

    .PHONY:clean CC=g++ CFLAGS=-Wall -g BIN=test_queue OBJS=Queue.o test_main.o $(BIN):$(OBJS) $(CC) $(C ...