[LeetCode]84. 柱状图中最大的矩形(java实现)单调栈

1. 题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 读题(需要重点注意的东西)

思路(单调栈):
单调栈能解决的问题: 找这个序列中每个数左边(或右边)离他最近的比他小的数下标是多少

本题的本质是找每一个数左边第一个比它小的数left[i]和右边第一个比他小的数right[i],(right[i] - left[i] - 1) * heights[i]就是当前列的最大的矩形面积

解法:

  1. 维护一个left栈,找到每个数左边第一个比它小的数,存储它的下标

  2. 维护一个right栈,找到每个数右边第一个比他小的数,存储它的下标

  3. (right[i] - left[i] - 1) * heights[i] 就是当前柱子最大的矩形面积

注: 单调栈的思想见[AcWing]830. 单调栈(C++实现)单调栈模板题

3. 解法

---------------------------------------------------解法---------------------------------------------------

class Solution {
    public int largestRectangleArea(int[] h) {
        int n = h.length;
        int[] left = new int[n + 10];
        int[] right = new int[n + 10];
        // 定义一个单调栈,用数组实现
        int[] stk = new int[n + 10];
        // 单调栈索引
        int tt = 0;
        // 从左往右扫描每个矩形左边的第一个比它小的数的下标
        for(int i = 0;i < n;i++){
            while(tt != 0 && h[stk[tt]] >= h[i]) tt--;
            if(tt == 0) left[i] = -1;
            else left[i] = stk[tt];
            stk[++tt] = i;
        }
        // 从右往左扫描每个矩形右边的第一个比它小的数的下标
        // 索引归0
        tt = 0;
        for(int i = n - 1;i >= 0;i--){
            while(tt != 0 && h[stk[tt]] >= h[i]) tt--;
            if(tt == 0) right[i] = n;
            else right[i] = stk[tt];
            stk[++tt] = i;
        }
        // 扫描一遍数组,求出答案
        int res = 0;
        for(int i = 0;i < n;i++)
            res = Math.max(res,(right[i] - left[i] - 1) * h[i]);
        return res;
    }
}

可能存在的问题:

4. 可能有帮助的前置习题

5. 所用到的数据结构与算法思想

6. 总结

本题主要有两个难点:

  1. 要知道本题的本质是找每一个数左边第一个比它小的数left[i]和右边第一个比他小的数right[i],(right[i] - left[i] - 1) * heights[i]就是当前列的最大的矩形面积
  2. 要会使用单调栈找左右的第一个比它小的位置在哪(要会使用单调栈):
    以找左边第一个比当前列小的数的位置为例,当遍历到当前列时,如果栈顶元素大于当前元素,栈顶元素出栈,直到栈顶元素小于当前元素,此时的栈顶元素就是第一个比它小的元素,如果栈找空了,则说明没有比它小的元素,将其置为-1,然后将当前元素进栈。

此外,可以直接使用栈Stack,也可以使用数组模拟栈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cloudeeeee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值