算法——柱状图中最大的矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
leetcode

解题思路:

  1. 首先想暴力该怎么做?
    就是依次遍历数组,求以每一个柱子为高度的最大面积,当遍历到一个元素的时候,在去找到它的左右两边第一个比它小的柱子的位置,这样就能取最大值。暴力的方法是N方的。
  2. 降低时间复杂度的方法。因为每次需要去遍历每个元素左右两边第一个比它小的位置,就很费时间。所以,可以先通过两次遍历,分别求每个元素在左右两个方向上,第一个比他小的元素的索引值,这样,就不需要每次都去重新找了。如果这个数组在一个方向上就是最小值,那么下标值就用-1或者数组的长度来代替计算。
  3. 通过单调栈的方法,就能通过一次遍历,寻找一个队列中,每个元素,在一个方向上的第一个比其小或者大的元素了。
  4. 最后,一次遍历数组,每次用之前存下来的左右两边第一个比它小的元素的下标之差,然后乘以其高度,就是以当前元素为高度的最大值,然后依次比较就是答案。
class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        // 利用两个数组,存储每个元素左右两边第一个比它小的元素的下标
        int[] l = new int[n], r = new int[n];
        Deque<Integer> stack = new LinkedList<>();
        int res = 0;

        for(int i = 0; i < n; i++) {
        	// 如果栈顶元素比它大,就不断弹出,因为在之前的比它大的元素已经不会被用到了
            while(!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                stack.pop();
            }
			// 弹到最后剩下的,就是第一个比它小的元素了
            l[i] = stack.isEmpty() ? -1 : stack.peek();

            stack.push(i);
        }

        stack = new LinkedList<>();
        for(int i = n - 1; i >= 0; i--) {
            while(!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                stack.pop();
            }

            r[i] = stack.isEmpty() ? n : stack.peek();

            stack.push(i);
        }

        for(int i = 0; i < n; i++) {
            res = Math.max(res, heights[i] * (r[i] - l[i] - 1));
        }

        return res;
    }
}
posted @ 2020-11-22 22:01  lippon  阅读(103)  评论(0编辑  收藏  举报