个人记录-LeetCode 84. Largest Rectangle in Histogram

来源:互联网 发布:淘宝发布宝贝没有品牌 编辑:程序博客网 时间:2024/06/03 19:51

问题:
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.

For example,
Given heights = [2,1,5,6,2,3],
return 10.

代码示例:
1、暴力解法,可行但超时。
基本思想一段范围内,最大的矩形等于最小的高度乘以宽。

public class Solution {    public int largestRectangleArea(int[] heights) {       if (heights == null || heights.length < 1) {            return 0;        }        return calculate(heights, 0, heights.length-1);    }    private int calculate(int[] heights, int begin, int end) {        if (begin >= 0 && end < heights.length) {            if (begin < end) {                int min = Integer.MAX_VALUE;                int minIndex = -1;                for (int i = begin; i <= end; ++i) {                    if (heights[i] < min) {                        min = heights[i];                        minIndex = i;                    }                }                int count = min * (end - begin + 1);                return Math.max(Math.max(count, calculate(heights, begin, minIndex-1)),                        calculate(heights, minIndex+1, end));            } else if (begin == end) {                return heights[begin];            }        }        return 0;    }}

2、分治法

public class Solution {    public int largestRectangleArea(int[] heights) {        if (heights == null || heights.length < 1) {            return 0;        }        return maxArea(heights, 0, heights.length-1);    }    int maxArea(int[] heights, int begin, int end) {        // 宽度为1的情况        if (begin == end) {            return heights[begin];        }        // 分治,结果由三种情况中的最大值决定        int m = begin + (end-begin)/2;        // 1 - 最大值存在于中间值以左        int area = maxArea(heights, begin, m);        // 2 - 最大值存在于中间值以右        area = Math.max(area, maxArea(heights, m+1, end));        // 3 - 最大值跨越中间值        area = Math.max(area, maxCombineArea(heights, begin, m, end));        return area;    }    int maxCombineArea(int[] heights, int begin, int m, int end) {        // 中间部分值包含m和m+1,往左右扩展        int i = m, j = m+1;        int area = 0, h = Math.min(heights[i], heights[j]);        while(i >= begin && j <= end) {            h = Math.min(h, Math.min(heights[i], heights[j]));            area = Math.max(area, (j-i+1) * h);            if (i == begin) {                ++j;            } else if (j == end) {                --i;            } else {                //外围哪边高,往哪边扩展                if (heights[i-1] > heights[j+1]) {                    --i;                } else {                    ++j;                }            }        }        return area;    }}

3、参考GeeksForGeeks
问题实际上可转化为:
1、求出每一个bar,作为一个范围内最矮的一个时,对应的大小。
2、求出所有的值后,其中最大的值就是最终结果。
这里的技巧是使用了一个stack,具体的分析还是参考上述链接,写的比较好,虽然是英文且是C++,但不妨碍阅读。

public class Solution {    public int largestRectangleArea(int[] heights) {        Stack<Integer> s = new Stack<>();        int maxArea = 0;        int tp;        int areaWithTop;        int i = 0;        while (i < heights.length) {            if (s.empty() || heights[s.peek()] <= heights[i]) {                s.push(i++);            } else {                tp = s.pop();                areaWithTop = heights[tp] * (s.empty() ? i : i - s.peek() - 1);                if (maxArea < areaWithTop) {                    maxArea = areaWithTop;                }            }        }        while (!s.empty()) {            tp = s.pop();            areaWithTop = heights[tp] * (s.empty() ? i : i - s.peek() - 1);            if (maxArea < areaWithTop) {                maxArea = areaWithTop;            }        }        return maxArea;    }}
0 0
原创粉丝点击