【单调栈】84. 柱状图中最大的矩形、60天刷题总结

news2025/1/13 3:10:55

提示:努力生活,开心、快乐的一天

文章目录

  • 84. 柱状图中最大的矩形
    • 💡解题思路
    • 🤔遇到的问题
    • 💻代码实现
    • 🎯题目总结
  • 总结
    • 数组
    • 链表
    • 哈希表
      • 数组作为哈希表
      • set作为哈希表
      • map作为哈希表
    • 字符串
      • 要不要使用库函数
      • 双指针法
      • 反转系列
      • KMP
    • 双指针
      • 数组篇
      • 字符串篇
      • 链表篇
      • N数之和篇
    • 栈与队列
    • 二叉树
    • 回溯
    • 回溯
    • 动态规划


84. 柱状图中最大的矩形

题目链接:84. 柱状图中最大的矩形

💡解题思路

  1. 本地单调栈的解法和接雨水的题目是遥相呼应的。
    42.接雨水 (opens new window)是找每个柱子左右两边第一个大于该柱子高度的柱子,而本题是找每个柱子左右两边第一个小于该柱子的柱子。这里就涉及到了单调栈很重要的性质,就是单调栈里的顺序,是从小到大还是从大到小。
    在题解42. 接雨水 (opens new window)中我讲解了接雨水的单调栈从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。
    那么因为本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈头(元素从栈头弹出)到栈底的顺序应该是从大到小的顺序!
    在这里插入图片描述
    只有栈里从大到小的顺序,才能保证栈顶元素找到左右两边第一个小于栈顶元素的柱子。
    所以本题单调栈的顺序正好与接雨水反过来。
    其实就是栈顶和栈顶的下一个元素以及要入栈的三个元素组成了我们要求最大面积的高度和宽度
  2. 主要就是分析清楚如下三种情况:
    情况一:当前遍历的元素heights[i]大于栈顶元素heights[st.top()]的情况
    情况二:当前遍历的元素heights[i]等于栈顶元素heights[st.top()]的情况
    情况三:当前遍历的元素heights[i]小于栈顶元素heights[st.top()]的情况

🤔遇到的问题

💻代码实现

var largestRectangleArea = function(heights) {
    let maxArea = 0;
    const stack = [];
    heights = [0,...heights,0]; // 数组头部加入元素0 数组尾部加入元素0
    for(let i = 0; i < heights.length; i++){ // 只用考虑情况一 当前遍历的元素heights[i]小于栈顶元素heights[stack[stack.length-1]]]的情况
        while(heights[i] < heights[stack[stack.length-1]]){// 当前bar比栈顶bar矮
            const stackTopIndex = stack.pop();// 栈顶元素出栈,并保存栈顶bar的索引
            let w = i - stack[stack.length -1] - 1;
            let h = heights[stackTopIndex]
            // 计算面积,并取最大面积
            maxArea = Math.max(maxArea, w * h);
        }
        stack.push(i);// 当前bar比栈顶bar高了,入栈
    }
    return maxArea;
};

🎯题目总结

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。


总结

总结多引用代码随想录中的图片参考

数组

在这里插入图片描述

链表

在这里插入图片描述

哈希表

常见的三种哈希结构:

  • 数组
  • set(集合)
  • map(映射)

数组作为哈希表

使用map确实可以,但使用map的空间消耗要比数组大一些,因为map要维护红黑树或者符号表,而且还要做哈希函数的运算。所以数组更加简单直接有效!

set作为哈希表

主要因为如下两点:

  • 数组的大小是有限的,受到系统栈空间(不是数据结构的栈)的限制。
  • 如果数组空间够大,但哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。

map作为哈希表

使用数组和set来做哈希法的局限:

  • 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
  • set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。
    map是一种<key, value>的结构,本题可以用key保存数值,用value在保存数值所在的下标。所以使用map最为合适。

字符串

要不要使用库函数

如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。

双指针法

双指针法在数组,链表和字符串中很常用。
其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

反转系列

当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。
先整体反转再局部反转或者先局部反转再整体反转

KMP

KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。
KMP的精髓所在就是前缀表,在KMP精讲 (opens new window)中提到了,什么是KMP,什么是前缀表,以及为什么要用前缀表。
前缀表:起始位置到下标i之前(包括i)的子串中,有多大长度的相同前缀后缀。
那么使用KMP可以解决两类经典问题:
匹配问题:28. 实现 strStr()(opens new window)
重复子串问题:459.重复的子字符串(opens new window)

前缀:指不包含最后一个字符的所有以第一个字符开头的连续子串。
后缀:指不包含第一个字符的所有以最后一个字符结尾的连续子串。

然后针对前缀表到底要不要减一,这其实是不同KMP实现的方式,我们在KMP精讲 (opens new window)中针对之前两个问题,分别给出了两个不同版本的的KMP实现。
其中主要理解j=next[x]这一步最为关键!

双指针

数组篇

通过两个指针在一个for循环下完成两个for循环的工作

字符串篇

使用双指针法,定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。,时间复杂度是O(n)。
其实很多数组(字符串)填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
在删除冗余空格的过程中,如果不注意代码效率,很容易写成了O(n^2)的时间复杂度。其实使用双指针法O(n)就可以搞定。

链表篇

使用双指针法来翻转链表,只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表。
使用快慢指针(双指针法),分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

N数之和篇

通过前后两个指针不算向中间逼近,在一个for循环下完成两个for循环的工作。

栈与队列

在栈与队列系列中,我们强调栈与队列的基础,也是很多同学容易忽视的点。

使用抽象程度越高的语言,越容易忽视其底层实现,而C++相对来说是比较接近底层的语言。

我们用栈实现队列,用队列实现栈来掌握的栈与队列的基本操作。

接着,通过括号匹配问题、字符串去重问题、逆波兰表达式问题来系统讲解了栈在系统中的应用,以及使用技巧。

通过求滑动窗口最大值,以及前K个高频元素介绍了两种队列:单调队列和优先级队列,这是特殊场景解决问题的利器,是一定要掌握的。

二叉树

涉及到二叉树的构造,无论普通二叉树还是二叉搜索树一定前序,都是先构造中节点。
求普通二叉树的属性,一般是后序,一般要通过递归函数的返回值做计算。
求二叉搜索树的属性,一定是中序了,要不白瞎了有序性了。
注意在普通二叉树的属性中,我用的是一般为后序,例如单纯求深度就用前序,二叉树:找所有路径 (opens new window)也用了前序,这是为了方便让父节点指向子节点。
所以求普通二叉树的属性还是要具体问题具体分析
在这里插入图片描述

回溯

在这里插入图片描述

回溯

在这里插入图片描述

动态规划

在这里插入图片描述

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

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

相关文章

Jmeter接口测试(十一):BeanShell脚本详解

BeanShell简介 BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些 语法和方法&#xff1b; BeanShell是一种松散类型的脚本语言&#xff1b; BeanShell是用Java写成的&#xff0c;一个小型的、免费的、可以下载、嵌入式的 Java源代码解释器&#xff0c;具…

Vue脚手架的安装和分析

一、Vue脚手架的安装步骤 &#xff08;一&#xff09;全局安装Vue脚手架 Window R&#xff0c;输入cmd进入电脑终端。 在终端中输入如下命令全局安装Vue脚手架&#xff1a; npm install -g vue/cli 下载过程中会警告&#xff0c;但不用关心这个。 &#xff08;二&#xff…

经管博士科研基础【26】海塞矩阵

1. 海塞矩阵 海塞矩阵是一个由多变量实值函数的所有二阶偏导数组成的方块矩阵。 一元函数就是二阶导,多元函数就是二阶偏导组成的矩阵。求向量函数最小值时可以使用,矩阵正定是最小值存在的充分条件。经济学中常常遇到求最优的问题,目标函数是多元非线性函数的极值问题,尚…

许战海方法论日文版正式发布,多家日媒转发

10月18日&#xff0c;日本财经媒体掀起了一场轻微的风潮&#xff0c;近40家权威媒体纷纷转发了一条引人注目的新闻:帆をあげて、海へ」、許戦海方法論の日本語版が正式に発表(扬帆起航&#xff1a;许战海方法论日文版正式发布)。 日本焦点新闻、阿波罗新闻、乐天新闻等权威媒体…

vue3 源码解析(1)— reactive 响应式实现

前言 本文是 vue3 源码解析系列的第一篇文章&#xff0c;项目代码的整体实现是参考了 v3.2.10 版本&#xff0c;项目整体架构可以参考之前我写过的文章 rollup 实现多模块打包。话不多说&#xff0c;让我们通过一个简单例子开始这个系列的文章。 举个例子 <!DOCTYPE html…

安科瑞带防逆流功能的数据通讯网关-安科瑞黄安南

AWT200 数据通讯网关应用于各种终端设备的数据采集与数据分析。用于实现设备的监测、控制、计算&#xff0c;为系统与设备之间建立通讯纽带&#xff0c;实现双向的数据通讯。实时监测并及时发现异常&#xff0c;同时自身根据用户规则进行逻辑判断&#xff0c;可以节省人力和通讯…

2023年面试测试工程师一般问什么问题?

面试和项目一起&#xff0c;是自学路上的两大拦路虎。面试测试工程师一般会被问什么问题&#xff0c;总结下来一般是下面这4类&#xff1a; 1.做好自我介绍 2.项目相关问题 3.技术相关问题 4.人事相关问题 接下来&#xff0c;主要从以上四个方向分别展开介绍。为了让大家更有获…

[ThinkPHP]The namespace “work“ is ambiguous (worker, workflow)

问题截图&#xff1a; 解决办法&#xff1a; console.php增加相关配置

PAM从入门到精通(二十三)

接前一篇文章&#xff1a;PAM从入门到精通&#xff08;二十二&#xff09; 本文参考&#xff1a; 《The Linux-PAM Application Developers Guide》 先再来重温一下PAM系统架构&#xff1a; 更加形象的形式&#xff1a; 七、PAM-API各函数源码详解 前边的文章讲解了各PAM-API…

方案聚焦:高可用的F5分布式云DNS负载均衡

DNS是实现互联网的主要技术之一。它也是网络基础设施的重要组成部分&#xff0c;DNS管理一个分布式和冗余的架构&#xff0c;确保高可用性和高质量的用户响应时间&#xff0c;因此拥有一个可用的、智能的、安全和可扩展的DNS基础设施是至关重要的。然而DNS没有真正的能力来分配…

如何有效取代FTP来帮助企业快速传输大文件

在互联网的发展历史上&#xff0c;FTP是一种具有里程碑意义的协议&#xff0c;它最早出现在1971年&#xff0c;是实现网络上文件传输的基础。FTP的优点是简单、稳定、兼容性强&#xff0c;可以在不同的操作系统和平台之间进行文件交换。然而&#xff0c;时代在进步&#xff0c;…

系统升级数量超微软预期,Win10/11盗版激活被封杀

声明&#xff1a;本文提供的命令、工具来自第三方网站&#xff0c;仅供学习交流使用&#xff0c;下载后24小时内删除&#xff0c;一切非法使用责任由使用者自行承担。 上月底 Win11 迎来了 Moment 4 功能更新&#xff0c;任务栏取消合并居然真的回归了。 巨硬终于妥协&#x…

软件开发行业的乱象——低价引流中途收费?299?399?

在当今的软件开发行业&#xff0c;存在着许多乱象。这些乱象不仅影响了软件开发的效率和效果&#xff0c;也给整个行业带来了许多负面影响。其中&#xff0c;价格方面是软件开发行业乱象的一个重要方面。 首先&#xff0c;从价格方面来看&#xff0c;软件开发行业的价格标准非常…

【均值漂移】mean-shift算法详解

Mean-shift算法是一种非参数密度估计算法&#xff0c;主要用于图像分割、目标跟踪和聚类等领域。其基本原理是以某个点为中心&#xff0c;计算该点周围所有点的密度&#xff0c;并将中心点移动到密度最大的位置&#xff0c;不断迭代&#xff0c;直到中心点不再移动或满足停止条…

常用智能优化算法改进策略---飞行游走篇(五种策略)可用于改进所有智能算法,让小白也会改进智能算法。...

本期文章将讲述常用智能优化算法改进策略---飞行游走篇&#xff0c;一共包含五种常见的改进策略&#xff1a; ①莱维飞行&#xff0c;②随机游走&#xff0c;③螺旋飞行&#xff0c;④高斯随机游走&#xff0c;⑤三角形游走 五种策略可以方便移植到其他任何智能算法的改进中&am…

开发常用的 Linux 命令知识积累

查看硬盘的使用情况df -h单元为根据大小适当显示&#xff0c;-m单位为M Linux中查找文件夹的命令是find命令。 全盘搜索&#xff0c;也可以指定目录搜索。find 搜索目录 -name 目标名字&#xff0c;find / -name file liunx自己总结常见命令 执行命令 含义 cd ~ 切换到登录…

了解docker

了解docker docker版本演进docker架构docker生态docker安装 docker版本演进 lxc&#xff1a; lxc 是最早的 linux 容器技术&#xff0c;早期版本的 docker 直接使用 lxc 来实现容器的底层功能。虽然使用者相对较少&#xff0c;但 lxc 项目仍在持续开发演进中libcontainer&#…

Flutter饱受争议的7个缺点,大家怎么看?

Flutter是一款由Google推出的跨平台移动应用开发框架&#xff0c;近年来备受关注。尽管Flutter在某些方面表现出色&#xff0c;但仍然有一些人对它的发展前景表示怀疑。近期一些文章针对Flutter的发展提出了不少质疑和批评&#xff0c;称其难以成为移动应用开发的“顶流明星”&…

Hacker 资讯 | 10 月下旬区块链黑客松活动汇总

「TinTin Hacker 快讯」是 TinTinLand 建立的一个资讯专栏&#xff0c;汇集近期线上线下的黑客松及 Grant&#xff0c;旨在帮助开发者和区块链爱好者获取最新的黑客松资讯&#xff0c;鼓励他们了解并根据自身情况参与不同的黑客松&#xff0c;更好地建设 Web3 生态。 ETHMiami …

1.初识MySQL

初识 MySQL 1.服务器处理客户端请求2.常用存储引擎3.关于存储引擎的一些操作3.1 查看当前服务器程序支持的存储引擎3.2 设置表的存储引擎3.2.1 创建表时指定存储引擎3.2.2 修改表的存储引擎 4.总结 MySQL 默认采用 TCP/IP 的方式来处理客户端与服务器连接过程。 1.服务器处理客…