084 Largest Rectangle in Histogram [Leetcode]

44 篇文章 0 订阅

题目描述:

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.

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

largest rectangle
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)的解法,也就是逐个判断当前的bar能够向左右延伸到什么位置为止,然后用bar的高度乘以延伸的宽度,并判断是否要更新最大值。

但这个复杂度是过不了大数据的。思考了很久也没有找到解决办法,因此参考了别人的解决方法。

思路:我们可以从左到右遍历所有bar,并将其push到一个stack中,如果当前bar的高度小于栈顶bar,我们pop出栈顶的bar,同时以该bar计算矩形面积。那么我们如何知道该bar的最左索引ln和最右索引rn呢?rn铁定就是当前遍历到的bar的索引,而ln则是当前的栈顶bar的索引,因为此时栈顶bar的高度一定小于pop出来的bar的高度,而栈中的bar的高度是递增的。

还有一个理解方式是:
如下图所示,从左到右处理直方,i=4时,小于当前栈顶(及直方3),于是在统计完区间[2,3]的最大值以后,消除掉黑色部分,然后把红色虚线部分作为一个大直方插入。因为,无论后面还是前面的直方,都不可能得到比目前栈顶元素更高的高度了。
这里写图片描述
这就意味着,可以维护一个递增的栈,每次比较栈顶与当前元素。如果当前元素小于栈顶元素,则入站,否则合并现有栈,直至栈顶元素小于当前元素。结尾入站元素0,重复合并一次。

上面的两个方法分别对应这两种实现方式。第一种是以index作为元素push到stack中,用index来求得矩形的宽度。在这里有一个难点,考虑例子{3,5,6,4,4},因为到第一个4的时候5和6都被pop出栈了,到第二个4的时候栈内元素为{3,4}对应的下标即{0,3}。计算宽度的时候,不能用栈顶元素的下标来计算宽度,而应该使用栈顶元素的下一个元素来进行计算,并且也要考虑到若栈内只有栈顶元素一个元素的情况。

第二种实现方式就是用height[index]的值放入stack中。这种情况下,需要将前面元素的值阶段成最右元素的值,实现起来操作更多一些,可以用stack的size来计算矩形的宽。这里就实现前一种方法了。

无论哪种方式,都要考虑到最后一个元素入栈后的情况。为了让程序更简洁,在height尾部放置一个最小值(如0),使得程序总是能够求取最后一个矩阵的大小。

代码如下:

class Solution {
public:
    int largestRectangleArea(vector<int>& height) {
        if(height.size() == 0) 
            return 0;
        //put a minimum number to calculate the area of last rectangle
        height.push_back(0);

        stack<int> h;
        int result(0), index(0), top(0);

        while(index < height.size()) {
            if(h.empty() || height[h.top()] < height[index]) {
                h.push(index++);
            }
            else {
                top = h.top();
                h.pop();
                //if stack had only 1 element, use index as width, else use current top index to calculate width
                top = h.empty() ? height[top] * index : height[top] * (index - h.top() - 1);
                result = result > top ? result : top;
            }
        }

        height.pop_back();
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值