给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]
。
图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10
个单位。
示例:
输入: [2,1,5,6,2,3] 输出: 10
思路:这道题可以说如果想实现O(n)的复杂度可以说是很巧了,答案都看了很久才看懂,这里只是列出来一些和网上的不一样的思考。首先列出参考的博客,可以说是图文并茂了:博客
先列出怎么解的,我们需要一个栈s,栈里存储的是递增序列,如果遇到一个待插入数字比栈顶元素小,那么就开始计算栈里的元素能围城的矩形面积,这里给出一张图:
假设栈里存储的已经是递增序列,这时来了一个比栈顶元素小的元素,那么所围成的面积一定不包括上图的红色矩形(只计算不包含红色矩形的面积,在红色矩形左边的矩阵中找)。但是这里有个问题,为什么一定不包含红色矩形呢?很多博客没有说。
扫描二维码关注公众号,回复:
2832001 查看本文章
也就是如下图所示:
为什么蓝色框的面积一定比红色框的面积大呢?这完全没有道理,因为红色的框可以更长,所以很多博客并没有解释。其实这道题很巧妙,并不是蓝色的框面积一定比红色的框大,应该是截止到蓝色的框的右边界为止(不包括红色小矩形),矩形面积最大的一定在红色小矩形的左边,换句话说,如上图所示的红色大矩形会在后面的情况中被包含进去。
如上图所示,处理完红色的小矩形左边的矩形,然后加入小红矩形,然后加入小蓝矩形,这时处理又开始了,这时便会计算如图紫色框的面积,而紫色框的面积就是之前讨论的大红色框的(包含小红色框)的矩形。所以其实基于这种栈的解法是考虑了所有的情况。
参考代码:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int res = 0;
heights.push_back(0);
stack<int> s;
for (int i = 0; i < heights.size(); i++) {
while (!s.empty() && heights[i] < heights[s.top()]) {
int tmp = s.top();
s.pop();
res = max(res, heights[tmp] * (s.empty() ? i : (i - 1 - s.top())));
}
s.push(i);
}
return res;
}
};