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.

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

解法一:

// Pruning optimize
class Solution {
public:
int largestRectangleArea(vector<int> &height) {
int res = ;
for (int i = ; i < height.size(); ++i) {
if (i + < height.size() && height[i] <= height[i + ]) {
continue;
}
int minH = height[i];
for (int j = i; j >= ; --j) {
minH = min(minH, height[j]);
int area = minH * (i - j + );
res = max(res, area);
}
}
return res;
}
};

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

解法二:

class Solution {
public:
int largestRectangleArea(vector<int> &height) {
int res = ;
stack<int> st;
height.push_back();
for (int i = ; i < height.size(); ++i) {
if (st.empty() || height[st.top()] < height[i]) {
st.push(i);
} else {
int cur = st.top(); st.pop();
res = max(res, height[cur] * (st.empty() ? i : (i - st.top() - )));
--i;
}
}
return res;
}
};

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

解法三:

class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int res = ;
stack<int> st;
heights.push_back();
for (int i = ; i < heights.size(); ++i) {
while (!st.empty() && heights[st.top()] >= heights[i]) {
int cur = st.top(); st.pop();
res = max(res, heights[cur] * (st.empty() ? i : (i - st.top() - )));
}
st.push(i);
}
return res;
}
};

类似题目:

Maximal Square

Maximal Rectangle

参考资料:

https://leetcode.com/problems/largest-rectangle-in-histogram/

https://leetcode.com/problems/largest-rectangle-in-histogram/discuss/28905/My-concise-C%2B%2B-solution-AC-90-ms

https://leetcode.com/problems/largest-rectangle-in-histogram/discuss/28902/5ms-O(n)-Java-solution-explained-(beats-96)

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 84. Largest Rectangle in Histogram 直方图中最大的矩形的更多相关文章

  1. [leetcode]84. Largest Rectangle in Histogram直方图中的最大矩形

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  2. [LeetCode] Largest Rectangle in Histogram 直方图中最大的矩形

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  3. LeetCode 84. Largest Rectangle in Histogram 直方图里的最大长方形

    原题 Given n non-negative integers representing the histogram's bar height where the width of each bar ...

  4. LeetCode 84. Largest Rectangle in Histogram 单调栈应用

    LeetCode 84. Largest Rectangle in Histogram 单调栈应用 leetcode+ 循环数组,求右边第一个大的数字 求一个数组中右边第一个比他大的数(单调栈 Lee ...

  5. 【LeetCode】84. Largest Rectangle in Histogram——直方图最大面积

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  6. leetCode 84.Largest Rectangle in Histogram (最大矩形直方图) 解题思路和方法

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  7. [leetcode]84.Largest Rectangle in Histogram ,O(n)解法剖析

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  8. [LeetCode#84]Largest Rectangle in Histogram

    Problem: Given n non-negative integers representing the histogram's bar height where the width of ea ...

  9. 【LeetCode】84. Largest Rectangle in Histogram 柱状图中最大的矩形(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 单调栈 日期 题目地址: https://leetc ...

随机推荐

  1. 错题shell

    1.判断/root/class21/inittab.txt文件是否大于100行,如果大于,则显示”inittab is a big file.”否者显示”inittab is a small file ...

  2. C++教程详解

    第一篇:基础篇 简介.环境配置.基本语法.注释.数据类型.变量类型.变量作用域.常量.修饰符类型. 存储类.运算符.循环.判断.函数.数字.数组.字符串.指针.引用.日期&时间. 基本的输入输 ...

  3. css 适配

    https://blog.csdn.net/weixin_35467885/article/details/80778992 1.通过link方法 link方法引入媒体类型其实就是在标签引用样式的时候 ...

  4. php+laravel依赖注入浅析

    laravel容器包含控制反转和依赖注入,使用起来就是,先把对象bind好,需要时可以直接使用make来取就好. 通常我们的调用如下. $config = $container->make('c ...

  5. ubuntu 18.04 安装mysql 遇到语言格式不兼容性问题解决

    安装mysql的时候,遇到了这样一个错误:perl: warning: Setting locale failed. perl: warning: Please check that your loc ...

  6. 基于 Swoole 的轻量级框架 CabalPHP

    CabalPHP CabalPHP 是一个基于Swoole的轻量.高效.全异步开源框架. 亮点 全异步单机超高性能,轻松分布式部署 支持HTTP.TCP.websocket等多种协议 完善数据库引擎, ...

  7. Kettle在windows上安装

    Kettle是一款国外开源的ETL工具,纯java编写,可以在Windows.Linux.Unix上运行,数据抽取高效稳定. 因为有个日常提数,工作日每天都要从数据库中提取数据,转换为excel,再以 ...

  8. git分支合并解决冲突

    git分支合并,解决冲突 1.手动解决冲突 手动解决冲突,需要使用编辑器,把所有文件中出现的冲突地方修改,然后再添加到暂存区再提交 >>>>>>brancha so ...

  9. php中trait的使用方法

    1.php中的trait是啥? 看上去既像类又像接口,其实都不是,Trait可以看做类的部分实现,可以混入一个或多个现有的PHP类中,其作用有两个:表明类可以做什么:提供模块化实现.Trait是一种代 ...

  10. ASP.NET Core 如何用 Cookie 来做身份验证

    前言 本示例完全是基于 ASP.NET Core 3.0.本文核心是要理解 Claim, ClaimsIdentity, ClaimsPrincipal,读者如果有疑问,可以参考文章 理解ASP.NE ...