0022柱状图中最大的矩形

柱状图中最大的矩形

编号:0022

试题来源:leetcode

题目描述

给定 n n n个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为1。

求在该柱形图中,能够勾勒出来的矩形的最大面积。

解答算法

算法思路

我们在思考最大的矩形的时候,可以任意选取一个柱子i,以其高度height[i]作为基准,向左右两侧进行拓展,如果拓展到的柱子的高度大于等于height[i],那么其可以作为以当前高度作为高的举行的一部分,如果小于,那么就可以得到其边界。

这样可以得到左右边界,有了左右边界,同时又有高度,就有了面积。

要得到左右边界,最笨的方法是对其进行两次遍历,每一次都要从当前位置i进行向左向右遍历,显然最坏的时间复杂度为 O ( n ) O(n) O(n)

我们可以使用一个栈stack存放单调的heigth[i]。考虑这样一个事实,如果有 h e i g h t [ i ] ≥ h e i g h t [ j ] 且 i < j height[i]\geq height[j]且i<j height[i]height[j]i<j,那么显然从大于 i i i的一个位置进行寻找边界,无论如何也不能选取 i i i作为左边界,因为 j j j挡住了 i i i,因此可以设置这样一个单调栈stack,存放height[i],以单调递增的顺序存放。

当我们处理位置i的时候,假设栈中已经存在 a 0 , a 1 , … , a k , a k + 1 , … , a m a_0,a_1,\dots ,a_k,a_{k+1},\dots,a_m a0,a1,,ak,ak+1,,am,那么假设 h e i g h t [ i ] > a k height[i] > a_k height[i]>ak,那么显然 a k + 1 , … , a m a_{k+1},\dots,a_m ak+1,,am都不能阻挡i的向左拓展,因此 k k k就是其左边界。要找到左边界,我们只需要将栈顶大于等于height[i]的值都pop出来,然后当前栈顶的坐标就是左边界。得到左边界后再将 h e i g t h [ i ] heigth[i] heigth[i]加入栈中,形成新的单调栈

代码实现

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();   //数组长度
        vector<int> left(n), right(n);  //存储左右两个边界
        
        stack<int> mono_stack;   //定义一个栈
        for (int i = 0; i < n; ++i) {   //对原数组从左向右进行遍历,得到左边界
            while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {  //当栈顶值大于等于当前值,移除
                mono_stack.pop();
            }
            left[i] = (mono_stack.empty() ? -1 : mono_stack.top());    //左边界的定义
            mono_stack.push(i);   //将当前值移入
        }

        mono_stack = stack<int>();    //对原数组进行从右向左进行遍历,得到右边界
        for (int i = n - 1; i >= 0; --i) {
            while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {
                mono_stack.pop();
            }
            right[i] = (mono_stack.empty() ? n : 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;
    }
};

复杂度分析

  • 时间复杂度:整个过程中对数组只进行一次遍历,可以看出在单调栈的操作过程中,我们对每个元素只进行了一次入栈操作,同时也最多只有一次出栈操作,因此时间复杂度为 O ( n ) O(n) O(n)
  • 空间复杂度:申请了左右边界数组,长度都为 n n n,因此空间复杂度为 O ( n ) O(n) O(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值