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

来源:互联网 发布:放置类挂机游戏源码 编辑:程序博客网 时间:2024/05/21 07:12

如图的直方图的高度为[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
原创粉丝点击