84. Largest Rectangle in Histogram

题目:

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.

链接: http://leetcode.com/problems/largest-rectangle-in-histogram/

题解:

也是一道难题。看过不少解答,最好的是维护一个递增栈(或者一个Deque), 当栈为空或者当前元素比栈顶元素大时,把当前元素入栈。否则把栈顶元素出栈,继续比较下一个栈顶元素与当前元素的大小。假如是1,2,3,4,1的话,运行到第2个1的时候,就要先出栈4,计算4 x 1,再是 3 x 2, 2 x 3,之后1 入栈, 最后遇到0计算 1 x 4。 一开始的array copy是为了创建最后一个数是0的情况,否则整个数组全部是递增的话没法pop()了。也要注意边界条件 - pop到最后时假如stack.isEmpty(),   则h[tmp] * i。

题外话: 上周五去草堂吃饭,点了一盘虎皮尖椒,吃完就胃部不适,过了一会整个胃灼烧感明显...让参加吃饭的各位扫兴了。最后是子龙兄在大雨中搀着我回家的,真是风雨同路人啊,感谢子龙兄!

Time Complexity - O(n), Space Complexity - O(n)。

public class Solution {
    public int largestRectangleArea(int[] height) {
        if(height == null || height.length == 0)
            return 0;
        int[] h = new int[height.length + 1];
        h = Arrays.copyOf(height, height.length + 1);           // last one is 0 so it's a pop()
        Stack<Integer> stack = new Stack<>();
        int i = 0, max = 0;
        
        while(i < h.length){
            if(stack.isEmpty() || h[stack.peek()] <= h[i])      // we use an increasing stack()
                stack.push(i++);
            else {
                int tmp = stack.pop();              //pop index in reverse order
                max = Math.max(max, h[tmp] * (stack.isEmpty() ? i : ((i - 1) - stack.peek())));     
            }
        }
        
        return max;
    }
}

 

二刷:

跟一刷类似,主要还是维护一个递增栈。下面我们详细分析一下

  1. 递增栈的技术除了这道题以外,还从一本<挑战程序设计>上看到过,据说在ACM里很常用。
  2. 这里我们用一个LinkedList list来代替stack, 首先设定一个用来遍历的变量i,以及一个用来存储最后结果的max。
  3. 接下来在遍历的过程中,我们维护一个递增栈, 栈的内容是heights数组的index,栈底部的元素就是当前的最小值。
  4. 当栈为空,或者当前位置的heights[i]大于等于栈顶元素的值heights[list.peekLast()],我们把这个元素入栈,然后计算下一个元素
  5. 否则,当前位置的heights[i]小于栈顶元素的值,我们要pop出栈顶元素,然后尝试更新max
    1. 假如pop之后,栈为空,那么这时候我们就用heights[lastIndex] * i, 就是从头开始最小的元素
    2. 否则,我们用之前的位置i - 1,减去栈顶元素位置的值。  这个要好好计算一下
  6. 假如遍历结束以后,栈还不为空,那么我们使用跟5一样的代码,依次pop出栈顶元素并且尝试更新max

Java:

Time Complexity - O(n), Space Complexity - O(n)。

public class Solution {
    public int largestRectangleArea(int[] heights) {
        if (heights == null || heights.length == 0) {
            return 0;
        }
        LinkedList<Integer> list = new LinkedList<>();
        int i = 0, max = 0;
        while (i < heights.length) {
            if (list.size() == 0 || heights[i] >= heights[list.peekLast()]) {
                list.addLast(i++);
            } else {
                int lastIndex = list.pollLast();
                max = Math.max(max, heights[lastIndex] * (list.isEmpty() ? i : (i - 1) - list.peekLast()));
            }
        }
        while (list.size() > 0) {
            int lastIndex = list.pollLast();
            max = Math.max(max, heights[lastIndex] * (list.isEmpty() ? i : (i - 1) - list.peekLast()));
        }
        return max;
    }
} 

 

三刷:

简化了一下code,但速度并不快。更快的方法是使用一个array来模拟栈的操作。

Java:

public class Solution {
    public int largestRectangleArea(int[] heights) {
        if (heights == null || heights.length == 0) return 0;
        Stack<Integer> stack = new Stack<>();
        int max = 0, idx = 0;
        while (idx <= heights.length) {
            int curHeight = (idx != heights.length) ? heights[idx] : 0;
            if (stack.isEmpty() || curHeight >= heights[stack.peek()]) {
                stack.push(idx++);
            } else {
                int height = heights[stack.pop()];
                int len = stack.isEmpty() ? idx : (idx - 1 - stack.peek());
                max = Math.max(max, len * height);
            }
        }
        return max;
    }
}

 

 

 

 

测试:

[2, 3, 4, 6, 7, 2]

[4, 2, 0, 3, 2, 5]

[1, 1, 1, 1, 2]

Reference:

http://www.cnblogs.com/lichen782/p/leetcode_Largest_Rectangle_in_Histogram.html 

https://leetcode.com/discuss/8079/my-modified-answer-from-geeksforgeeks-in-java

https://leetcode.com/discuss/22431/o-n-stack-based-java-solution

https://leetcode.com/discuss/90454/5ms-o-n-java-solution-explained-beats-96%25

https://leetcode.com/discuss/103600/java-o-n-beats-96-42%25

https://leetcode.com/discuss/22431/o-n-stack-based-java-solution

https://leetcode.com/discuss/12780/my-concise-c-solution-ac-90-ms

https://leetcode.com/discuss/36608/my-concise-code-20ms-stack-based-o-n-one-trick-used

https://leetcode.com/discuss/91902/share-my-2ms-java-solution-beats-100%25-java-submissions

https://leetcode.com/discuss/70983/4ms-java-solution-using-o-n-stack-space-o-n-time

 

posted @ 2015-04-18 12:04  YRB  阅读(550)  评论(0)    收藏  举报