LeetCode 84 柱状图中最大的矩形 - 单调栈解法

LeetCode 84 柱状图中最大的矩形 - 单调栈解法

https://leetcode.cn/problems/largest-rectangle-in-histogram/description/?envType=study-plan-v2&envId=top-100-liked

说明

下面保留了两种写法:

  • 第一段是枚举区间的思路。
  • 第二段是单调栈优化写法,核心是“在弹栈时结算面积”。
class Solution {

    public int largestRectangleArea(int[] heights) {

        int n = heights.length;

        int ans = 0;

        // 枚举 [i,j]

        for (int i = 0; i < n; i++) {

            int min = Integer.MAX_VALUE;

            int area = 0;

            for (int j = i; j < n; j++) {

                if (heights[j] < min) {

                    min = heights[j];

                    area = (j - i + 1) * min;

  

                } else {

                    area += min;

                }

                ans = Math.max(ans, area);

            }

        }

        return ans;

    }

  

    public int largestRectangleArea1(int[] heights) {

        int n = heights.length;

        int ans = 0;

  

        // 递增栈

        Deque<Integer> deque = new LinkedList<>();

        for(int i = 0;i<n;i++){

            while (!deque.isEmpty()&&heights[i]<heights[deque.peek()]) {

                int top = deque.pop();

                // height[i]<height[top], 可以计算 高为 height[top] 的矩形

                // 左边界是弹出后栈顶, 有边界是height[i]

                int left = -1;

                if (!deque.isEmpty()) {

                    left = deque.peek();

                }

                int area = (i-1-(left+1)+1)*heights[top];

                ans = Math.max(ans, area);

            }

            deque.push(i);

        }

        // 可能栈中还有

        while (!deque.isEmpty()) {

            int top = deque.pop();

            // 右侧找不到比 height[top]小的, 因此 right = n;

            int right = n;

            int left = -1;

            if (!deque.isEmpty()) {

                left = deque.peek();

            }

            int area = (right-1-(left+1)+1)*heights[top];

            ans = Math.max(ans, area);

        }

        return ans;

    }

}

单调栈

  • 遇到相等高度时继续入栈。因为本题在弹栈时计算面积,要保证每个位置都能被结算一次。