LeetCode 84. Largest Rectangle in Histogram

这道问题通过单调栈求解,维护一个单调递减的栈,遍历柱状图,计算每个柱子的左右边界,从而得到最大矩形面积。栈中的元素高度逐渐减小,用于确定当前柱子的左边界,而右边界由遍历顺序决定。最终遍历所有柱子,找到最大面积。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode 84. Largest Rectangle in Histogram

题目

Given an array of integers heights representing the histogram’s bar height where the width of each bar is 1, return the area of the largest rectangle in the histogram.

翻译

给定一个整数数组heights,表示柱状图的高度,每个柱子的宽度为1,返回柱状图中最大矩形的面积。

解析

这道题目的解法是单调栈,单调栈的思路是,维护一个单调递减的栈,当遇到比栈顶元素小的元素时,就计算栈顶元素的面积,然后弹出栈顶元素,直到栈顶元素大于等于当前元素,然后将当前元素入栈。

选用单调栈的原因

这道题目的解法是单调栈,这里介绍一下为什么选用单调栈。
因为计算柱状图中最大矩形的面积,需要计算每个柱子的左边界和右边界,然后计算面积,这里的左边界和右边界都是指比当前柱子小的柱子,所以可以使用单调栈来计算左边界和右边界。

计算右边界

计算右边界的时候,需要从左往右遍历,遍历到的柱子如果比栈顶元素小,当前柱子就是栈顶元素的右边界,然后弹出栈顶元素,直到栈顶元素小于等于当前元素,然后将当前元素入栈。

计算右边界

因为使用的是递减栈,所以栈中的元素是单调递减的,所以栈中的元素的左边界就是栈顶元素的下一个元素,如果栈为空,说明当前元素是最小的元素,左边界就是-1。

计算面积

计算面积的时候,需要计算当前柱子的高度和左边界和右边界的距离,然后计算面积,最后取最大值。

代码

Java


class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        int[] left = new int[n];
        int[] right = new int[n];
        Deque<Integer> stack = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                stack.pop();
            }
            left[i] = stack.isEmpty() ? -1 : stack.peek();
            stack.push(i);
        }
        stack.clear();
        for (int i = n - 1; i >= 0; i--) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                stack.pop();
            }
            right[i] = stack.isEmpty() ? n : stack.peek();
            stack.push(i);
        }
        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
        }
        return ans;
    }
}

C++


class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        vector<int> left(n), right(n, n);
        stack<int> mono_stack;
        for (int i = 0; i < n; ++i) {
            while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {
                right[mono_stack.top()] = i;
                mono_stack.pop();
            }
            left[i] = (mono_stack.empty() ? -1 : mono_stack.top());
            mono_stack.push(i);
        }
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans = max(ans, (right[i] - left[i] - 1) * heights[i]);
        }
        return ans;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值