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 heights = [2,1,5,6,2,3],
return 10.

给定一组非负数,然后求出最大面积(画到数轴上,宽度都是1)。

 这道题感觉还是比较难的,反正我没有做出来。

刚开始我想的是比较暴力的算法,就是遍历每个数字,然后以这个数字为中心,向两边延伸,找到最大的面积(最小也是他本身)。但是这样超时了。

public class Solution {
    public int largestRectangleArea(int[] heights) {
        int len = heights.length;
        int high ,result = 0, ans;
        int[] flag = new int[len];
        for( int i = 0;i<len;i++){
            if( flag[i] == 1)
                continue;
            high = heights[i];
            ans = high;
            int j = i+1;
            while( j<len){
                if( heights[j] > high){
                    ans+=high;
                }else if( heights[j] == high){
                    ans+=high;
                    flag[j] = 1;
                }
                else
                    break;
                j++;
            }
            j = i-1;
            while( j >= 0){
                if( heights[j] >= high){
                    ans+=high;
                }
                else
                    break;
                j--;
            }
            result = result>ans?result:ans;
        }
        return result;
    }
}

然后想的是利用动态规划,但是代码一直有问题,也没有通过。

后来看了答案, 发现也是类似动态规划的想法,运用得很巧妙,找到左边界和右边界,然后就顺利找出了。

左边界:指的是从0-i这个范围内,以heights[i]为高度,向左延伸的最大位置。

右边界同理。

public class Solution {
    public int largestRectangleArea(int[] heights) {


        int len = heights.length;
        int result = 0;
        if( len == 0)
            return 0;

        int[] left = new int[len];
        int[] right = new int[len];

        left[0] = 0;
        for( int i = 1;i<len;i++){
            int CurLeft = i-1;
            while( CurLeft >= 0 && heights[CurLeft]>=heights[i]){
                CurLeft = left[CurLeft]-1;
            }
            left[i] = CurLeft+1;
        }
        right[len-1] = len-1;
        for( int i = len-2;i>=0;i--){
            int CurRight = i+1;
            while( CurRight<len && heights[CurRight]>=heights[i])
                CurRight = right[CurRight]+1;
            right[i] = CurRight-1;
        }
        for( int i = 0;i<len;i++){
            result = Math.max(result,(right[i]-left[i]+1)*(heights[i]));
        }
        return result;
    }
}