代码随想录算法训练营第六十天丨 单调栈03

news2025/1/11 6:06:17

84.柱状图中最大的矩形

思路

单调栈

本地单调栈的解法和接雨水的题目是遥相呼应的。

为什么这么说呢,42. 接雨水 (opens new window)是找每个柱子左右两边第一个大于该柱子高度的柱子,而本题是找每个柱子左右两边第一个小于该柱子的柱子。

这里就涉及到了单调栈很重要的性质,就是单调栈里的顺序,是从小到大还是从大到小

在题解42. 接雨水 (opens new window)中讲解了接雨水的单调栈从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。

那么因为本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈头(元素从栈头弹出)到栈底的顺序应该是从大到小的顺序!

来举一个例子,如图:

只有栈里从大到小的顺序,才能保证栈顶元素找到左右两边第一个小于栈顶元素的柱子。

所以本题单调栈的顺序正好与接雨水反过来。

此时大家应该可以发现其实就是栈顶和栈顶的下一个元素以及要入栈的三个元素组成了我们要求最大面积的高度和宽度

理解这一点,对单调栈就掌握的比较到位了。

除了栈内元素顺序和接雨水不同,剩下的逻辑就都差不多了,在题解42. 接雨水 (opens new window)我已经对单调栈的各个方面做了详细讲解,这里就不赘述了。

主要就是分析清楚如下三种情况:

  • 情况一:当前遍历的元素heights[i]大于栈顶元素heights[st.top()]的情况
  • 情况二:当前遍历的元素heights[i]等于栈顶元素heights[st.top()]的情况
  • 情况三:当前遍历的元素heights[i]小于栈顶元素heights[st.top()]的情况

代码如下:

class Solution {
    public int largestRectangleArea(int[] heights) {
        //单调递减栈
        Stack<Integer> st = new Stack<>();
        //对原数组进行扩容,首尾加一个0就行
        int[] newHeights = new int[heights.length + 2];
        for (int i = 0; i < heights.length; i++) {
            newHeights[i + 1] = heights[i];
        }
        heights = newHeights;
        st.push(0);
        int res = 0;
        // 第一个元素已经入栈,从下标1开始
        for (int i = 1; i < heights.length; i++) {
            if (heights[i] > heights[st.peek()]) {// 情况一
                st.push(i);
            } else if (heights[i] == heights[st.peek()]) {// 情况二
                st.pop();
                st.push(i);
            } else {//
                while (heights[i] < heights[st.peek()]) {// 注意是while
                    int mid = st.pop();
                    int left = st.peek();
                    int right = i;
                    int w = right - left - 1;
                    int h = heights[mid];
                    res = Math.max(res, w * h);
                }
                st.push(i);
            }
        }
        return res;
    }
}

细心的录友会发现,我在 height数组上后,都加了一个元素0, 为什么这么做呢?

首先来说末尾为什么要加元素0?

如果数组本身就是升序的,例如[2,4,6,8],那么入栈之后 都是单调递减,一直都没有走 情况三 计算结果的哪一步,所以最后输出的就是0了。 如图:

那么结尾加一个0,就会让栈里的所有元素,走到情况三的逻辑。

开头为什么要加元素0?

如果数组本身是降序的,例如 [8,6,4,2],在 8 入栈后,6 开始与8 进行比较,此时我们得到 mid(8),rigt(6),但是得不到 left。

(mid、left,right 都是对应版本一里的逻辑)

因为 将 8 弹出之后,栈里没有元素了,那么为了避免空栈取值,直接跳过了计算结果的逻辑。

之后又将6 加入栈(此时8已经弹出了),然后 就是 4 与 栈口元素 8 进行比较,周而复始,那么计算的最后结果resutl就是0。 如图所示:

所以我们需要在 height数组前后各加一个元素0。


代码随想录一刷终于完结了!!这六十天的自律太爽了,准备二刷!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1232355.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器人制作开源方案 | 智能照科植物花架

作者&#xff1a;付菲菲、于海鑫、王子敏单位&#xff1a;黑河学院指导老师&#xff1a;索向峰、李岩 1. 概述 1.1设计背景​ 随着时代的发展&#xff0c;城市化脚步加快、城市人口密度越来越大、城市生活节奏快压力大作息难成规律。城市建筑建筑面积迅速增加、而绿…

SpringCloud 微服务全栈体系(十五)

第十一章 分布式搜索引擎 elasticsearch 五、RestClient 操作文档 为了与索引库操作分离&#xff0c;再次参加一个测试类&#xff0c;做两件事情&#xff1a; 初始化 RestHighLevelClient酒店数据在数据库&#xff0c;需要利用 IHotelService 去查询&#xff0c;所以注入这个接…

Pandas数据集的合并与连接merge()方法_Python数据分析与可视化

数据集的合并与连接 merge()解析merge()的主要参数 merge()解析 merge()可根据一个或者多个键将不同的DataFrame连接在一起&#xff0c;类似于SQL数据库中的合并操作。 数据连接的类型 一对一的连接&#xff1a; df1 pd.DataFrame({employee: [Bob, Jake, Lisa, Sue], grou…

HDCTF2023 - Reverse方向全WP

文章目录 [HDCTF 2023]easy_re[HDCTF 2023]easy_asm[HDCTF 2023]fake_game[HDCTF 2023]enc[HDCTF 2023]double_code[HDCTF 2023]买了些什么呢[HDCTF2023]basketball [HDCTF 2023]easy_re UPX壳&#xff0c;脱壳 一个base64编码。 [HDCTF 2023]easy_asm ida打开后可以看到xor 10…

深入了解千兆光模块和万兆光模块

光模块是一种光电转换设备&#xff0c;在发射端&#xff0c;光模块能够将设备产生的电信号转换成光信号从而实现在光纤介质中传输&#xff0c;在接收端光模块将接收到的光信号再次转换为设备能够识别的电信号&#xff0c;从而实现高速、精准的数据传输。例如&#xff0c;在线视…

V100 GPU服务器安装CUDA教程

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

常见树种(贵州省):009楠木、樟木、桂木种类

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、楠木 …

python实现炫酷的屏幕保护程序

shigen日更文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 上次的文章如何实现一个下班倒计时程序的阅读量很高&#xff0c;觉得也很实用酷炫&#xff0c;下边是昨天的体验…

Leetcode刷题详解——删除并获得点数

1. 题目链接&#xff1a;740. 删除并获得点数 2. 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;你可以对它进行一些操作。 每次操作中&#xff0c;选择任意一个 nums[i] &#xff0c;删除它并获得 nums[i] 的点数。之后&#xff0c;你必须删除 所有 等于 nums[i] …

如何使用http来获取thingsbord中的设备数据

背景 有个读者问我,他想做tb的二次开发,想要通过一个接口来查询设备的遥测数据。 于是我给他写了这篇文章。 具体实现 由于他使用的是cloud版本,于是我使用cloud来做演示 文档的接口 https://thingsboard.cloud/swagger-ui/#/telemetry-controller/getTimeseriesUsing…

一道简单的积分题目

题目如下图&#xff1a; 解法1&#xff1a; 解法2&#xff1a; 解法3&#xff1a; 错误做法&#xff1a; 在 x ∈ ( 0 , ∞ ) 上有 ln ⁡ x < x &#xff0c;令 f ( x ) ln ⁡ x 1 x 2 &#xff0c; g ( x ) &#xff1d; x 1 x 2 ∴ f ( x ) < g ( x ) &#x…

【汇编】“转移”综述、操作符offset、jmp指令

文章目录 前言一、转移综述1.1 :背景&#xff1a;1.2 转移指令1.3 转移指令的分类按转移行为根据指令对IP修改的范围不同 二、操作符offset2.1 offset操作符是干什么的&#xff1f;标号是什么&#xff1f; 2.2 nop是什么&#xff1f; 三、jmp指令3.1 jmp指令的功能3.2 jmp指令&…

Vue移动 HTML 元素到指定位置 teleport 标签

teleport 标签&#xff1a;用于将组件中的 HTML 元素移动到任意的位置。 使用 teleport 标签移动 HTML 元素&#xff1a; <!-- 将 teleport 中的内容移动到 body 标签中 --> <teleport to"body"><div><h3>我是第三层组件的标题</h3>…

腾讯云轻量数据库1核1G性能测评、租用费用和详细介绍

腾讯云轻量数据库服务采用腾讯云自研的新一代云原生数据库 TDSQL-C&#xff0c;融合了传统数据库、云计算与新硬件技术的优势&#xff0c;100%兼容 MySQL&#xff0c;实现超百万级 QPS 的高吞吐&#xff0c;128TB 海量分布式智能存储&#xff0c;保障数据安全可靠。腾讯云百科t…

Android Termux安装MySQL,内网穿透实现公网远程访问

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…

【Linux】:进程间通信和日志模拟

进程间通信 一.基本概念二.简单的通信-管道(匿名管道)1.建立通信信道2.通信接口 三.命名管道三.模拟命名管道通信&#xff08;加上日志&#xff09;1.完整代码2.基本使用 一.基本概念 是什么 两个或多个进程实现数据层面的交互。 因为进程独立性的存在&#xff0c;导致进程间…

【前段基础入门之】=>CSS3新特性 BFC

什么是BFC( 概念) W3C 上对 BFC 的定义&#xff1a; MDN 上对 BFC 的定义&#xff1a; 简而言之 开启了BFC能解决什么问题 元素开启 BFC 后&#xff0c;其子元素不会再产生 margin 塌陷问题元素开启 BFC 后&#xff0c;自己不会被其他浮动元素所覆盖元素开启 BFC 后&#xff0…

【Java】多线程-wait/notify

1、wait和notify Java的多线程中&#xff0c;线程的执行顺序和时间都是不定的。为了控制线程的调度顺序&#xff0c;前面我们引入了join()方法。 但是join()只能在线程执行完后&#xff0c;才能执行其他线程&#xff0c;有没有什么方法可以在线程执行顺序中来调度其他线程呢&…

代码随想录 Day50 单调栈 LeetCodeT503 下一个最大元素II T42接雨水

前言 前面我们说到了单调栈的第一题,下一个最大元素I,其实今天的两道题都是对他的变种,知道第一个单调栈的思想能够想清楚,其实这道题是很简单的 考虑好三个状态,大于等于小于,其实对于前面这些题目只要细心的小伙伴就会发现其实小于和等于的处理是一样的都是直接入栈,只有大于…

灵魂拷问std::enable_shared_from_this,揭秘实现原理

灵魂拷问std::enable_shared_from_this&#xff0c;揭秘实现原理 引言 在C编程中&#xff0c;使用智能指针是一种安全管理对象生命周期的方式。std::shared_ptr是一种允许多个指针共享对象所有权的智能指针。然而&#xff0c;当一个对象需要获取对自身的shared_ptr时&#xff0…