LeetCode84 --Largest Rectangle in Histogram

来源:互联网 发布:淘宝买东西物流不更新 编辑:程序博客网 时间:2024/06/05 09:27
 

Largest Rectangle in Histogram


Question:

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.

解法一

使用动态规划,用left[i]表示第i个柱子可以最多向左延伸至第left[i]个柱子,形成一个矩形,right[i]则表示向右延伸。遍历两次,分别计算出这两个数组。

再遍历一次,即可求出所有的柱子可以形成的最大的矩形面积。为了减少边界的判断,可以使用哨兵,在两端添加两个柱子高度都为-1.

01//============================================================================
02// Name        : MaxRectagle.java
03// Author      : GaoTong
04// Date        : 2014/9/5
05// Copyright   : www.acmerblog.com
06//============================================================================
07public class MaxRectagle {
08    public static void main(String args[]){
09        int height[] = {2,1,5,6,2,3};
10        int ans = getMaxRectangle(height);
11        System.out.println(ans);
12    }
13 
14    public static int getMaxRectangle (int heights[]){
15        int ans = 0;
16        int n = heights.length;
17        int left[] = new int[n+1];
18        int right[] = new int[n+1];
19        processLR(heights, left, right);
20        for(int i=1; i<=n; i++){
21            int tmp = (right[i]-left[i]+1) * heights[i-1];
22            if( ans < tmp)
23                ans = tmp;
24        }
25        return ans;
26    }
27 
28    public static void processLR(int heights[], int left[], int right[]){
29        int n = heights.length;
30        //用临时数组,设置两个哨兵
31        int tempArr[] = new int[n+2];
32        tempArr[0] = -1;
33        for(int i=1; i<=n; i++) tempArr[i] = heights[i-1];
34        tempArr[tempArr.length-1] = -1;
35 
36        for(int i=1; i<=n; i++){
37            int k = i;
38            while( tempArr[i] <= tempArr[k-1])
39                k = left[k-1];
40            left[i] = k;
41        }
42 
43        for(int i=n; i>0; i--){
44            int k = i;
45            while(  tempArr[i] <= tempArr[k+1])
46                 k = right[k+1];
47            right[i] = k;
48        }
49    }
50}

算法的时间复杂度为 O(n)。 再求left[]和right[]时,虽然里面有while循环,但可以保证复杂度为O(n)


Analysis:

When solving this problem, the straightforward approach is to consider all possible cases, i.e., we begin with the ith rectangle, and then enumerate the remaining rectangles after the ith rectangle, each time, we need to compare the area with the maximum area. The time complexity is O(n^2).

[java] view plain copy
  1. public static int largestRectangleArea(int[] height) {  
  2.     if (height == null || height.length <= 0return 0;  
  3.     int maxArea = 0;  
  4.     for (int i = 0; i < height.length; i++) {  
  5.         int minHeight = height[i];  
  6.         // we need to begin with i, otherwise, we can not pass the test case  
  7.         // in which the rectangle array is like [5, 0, 5, 0]  
  8.         for (int j = i; j < height.length; j++) {  
  9.             if (height[j] < minHeight) {  
  10.                 minHeight = height[j];  
  11.             }  
  12.             int tempArea = minHeight * (j - i + 1);  
  13.             if (tempArea > maxArea) {  
  14.                 maxArea = tempArea;  
  15.             }  
  16.         }  
  17.     }  
  18.     return maxArea;  
  19. }  

Actually, we can decrease the complexity by using stack to keep track of the height and start indexes. Compare the current height with previous one.

Case 1: current > previous (top of height stack)
Push current height and index as candidate rectangle start position.

Case 2: current = previous
Ignore.

Case 3: current < previous
Need keep popping out previous heights, and compute the candidate rectangle with height and width (current index - previous index). Push the height and index to stacks.

(Note: it is better use another different example to walk through the steps, and you will understand it better).

[java] view plain copy
  1. public int largestRectangleArea(int[] height) {  
  2.     if (height == null || height.length == 0return 0;  
  3.       
  4.     int maxArea = 0;  
  5.     Stack<Integer> stackHeight = new Stack<Integer>();  
  6.     Stack<Integer> stackIndex = new Stack<Integer>();  
  7.       
  8.     for (int i = 0; i < height.length; i++) {  
  9.         //case 1  
  10.         if (stackHeight.isEmpty() || height[i] > stackHeight.peek()) {  
  11.             stackHeight.push(height[i]);  
  12.             stackIndex.push(i);  
  13.         } else if (height[i] < stackHeight.peek()) {  
  14.             // case 3  
  15.             int lastIndex = 0;  
  16.             while (stackHeight.isEmpty() == false && height[i] < stackHeight.peek()) {  
  17.                 lastIndex = stackIndex.pop();  
  18.                 int tempArea = stackHeight.pop() * (i - lastIndex);  
  19.                 if (maxArea < tempArea) {  
  20.                     maxArea = tempArea;  
  21.                 }  
  22.             }  
  23.             stackHeight.push(height[i]);  
  24.             stackIndex.push(lastIndex);  
  25.         }  
  26.     }  
  27.       
  28.     while(stackHeight.isEmpty() == false) {  
  29.         int tempArea = stackHeight.pop() * (height.length - stackIndex.pop());  
  30.         if (tempArea > maxArea) {  
  31.             maxArea = tempArea;  
  32.         }  
  33.     }  
  34.     return maxArea;  
  35. }  

题解:

如果高度一致都是递增的就一直压入栈,一旦遇到一个高度减小的,就计算栈里面能够组成的最大四边形面积(一个个出栈分别计算四边形面积)


代码:

[java] view plain copy
  1. static public int largestRectangleArea(int[] height) {  
  2.         Stack<Integer> stack=new Stack<>();  
  3.         int n=height.length;  
  4.         int maxarea=0;  
  5.         int i=0;  
  6.         int temp=0;  
  7.         int tempTop=0;  
  8.         while(i<=n)  
  9.         {  
  10.             temp=(i==n?0:height[i]);  
  11.             if(stack.isEmpty()||height[stack.peek()]<=temp)  
  12.             {  
  13.                 stack.push(i);  
  14.                 i++;  
  15.             }  
  16.             else {  
  17.                 tempTop=height[stack.pop()];  
  18.                 maxarea=Math.max(maxarea,tempTop*(stack.isEmpty()?i:i-1-stack.peek()) );  
  19.             }  
  20.         }  
  21.   
  22.           
  23.          return maxarea;  
  24.            
  25.           
  26.     }      
/*
public class Solution {
    public int largestRectangleArea(int[] heights) {
        if (height == null || height.length == 0) {
            return 0;
        }
        
        Stack<Integer> stack = new Stack<Integer>();
        int max = 0;
        for (int i = 0; i <= height.length; i++) {
            int curt = (i == height.length) ? -1 : height[i];
            while (!stack.isEmpty() && curt <= height[stack.peek()]) {
                int h = height[stack.pop()];
                int w = stack.isEmpty() ? i : i - stack.peek() - 1;
                max = Math.max(max, h * w);
            }
            stack.push(i);
        }  
        return max;
    }
}
 */


0 0