Largest Rectangle in Histogram 直方图中最大的矩形

如图的直方图的高度为[2, 1, 5, 6, 2, 3] ,每个bar的宽度为1, 能够形成的最大面积的矩形为 2 * 5 = 10。

在这里我会介绍2种解法,一种是很直观的时间复杂度为O(n^2)的解法,另一种是很巧妙地利用了栈的时间复杂度O(n)的解法。


对于每个长条(bar),我们将它看成是矩形中最小长度的长条。对于每个长条,我们都能计算出该长条下,最大的面积。

所以,最终我们能够找到最大的面积。

比如以第一个长条2为例,以它进行周围扩展的话,比它小的左边的是没有了;比它小的右边也没有(它的右边是1),

所以,这个长条能形成的最大面积是2.

再以5为例子,比它小的左边没有,比它小的右边是6,所以它能形成的最大的面积是 2 * 5 。


解法1(复杂度O(n^2))

按照上述思路的基础解法。我们的目的就是寻找到比当前长条小的左smallerIndex, 和右 smallerIndex。

代码:

    public int largestRectangleArea(int[] heights) {
        int maxArea = 0;
        for (int i = 0; i < heights.length; i++) {
            maxArea = Math.max(maxArea, calRecArea(heights, i));
        }
        return maxArea;
    }

    private int calRecArea(int[] heights, int index) {
        int left = index - 1, right = index + 1;
        while (left >= 0 && heights[left] >= heights[index])
            left--;
        while (right < heights.length && heights[right] >= heights[index])
            right++;
        return (right - left - 1) * heights[index];
    }

解法2:


如何能更方便的知道比当前bar更小的左,右bar的index 呢?

我们可以从左到右遍历这个height数组,同时维护一个stack。

每一个bar都会入栈一次, 当碰到更小的height的时候,pop()

当一个ba pop()了,我们将弹出的bar作为高度最小的bar.

那么此时,这个bar的leftSmalIerIndex 和 rightSmallerIndex 是什么呢?

当前遍历到的index 正是 rightSmallerIndex, 栈顶正是leftSmallerIndex。


代码:


    private int largestRectangleAreaStack(int[] heights) {
        int i = 0;
        int maxArea = 0;
        int curArea = 0;
        Stack<Integer> store = new Stack<>(); // to store the left smaller index
        while (i < heights.length) {
            if (store.empty() || heights[store.peek()] <= heights[i]) {
                store.add(i);
                i++;
            } else {
                int curTop = store.pop();
                // the ‘left smaller index’ is previous (previous to tp) item in stack and ‘right smaller index’ is ‘i’ (current index).
                if (!store.isEmpty()) {
                    curArea = heights[curTop] * (i - store.peek() - 1);
                } else {
                    curArea = heights[curTop] * i;
                }
                maxArea = Math.max(maxArea, curArea);
            }
        }
        while (!store.isEmpty()) {
            int curTop = store.pop();
            if (!store.isEmpty()) {
                curArea = heights[curTop] * (i - store.peek() - 1);
            } else {
                curArea = heights[curTop] * i;
            }
            maxArea = Math.max(maxArea, curArea);
        }
        return maxArea;
    }


参考:

http://www.geeksforgeeks.org/largest-rectangle-under-histogram/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值