代码随想录算法训练营Day60 | 84. 柱状图中最大的矩形

news2024/9/23 23:26:42

文章目录

  • 84. 柱状图中最大的矩形
    • 首尾加 0
    • 双指针

84. 柱状图中最大的矩形

题目链接 | 解题思路

本题和接雨水的题目相互呼应,但是难度略有提升,同样是一道非常棒的题!

在接雨水中,需要找到每一列的左侧最大值和右侧最大值;在本题中,需要找到每一列的左侧第一个更小值和右侧第一个更小值。这个要求的变化加大了双指针的难度,所以优先讨论更加适用的单调栈解法。

和上一题一样按行来计算矩形面积,对于固定的一列,需要这一列的高度、对应的左边界、对应的右边界。但这一题,单调栈的储存顺序发生了变化。

在这里插入图片描述

  1. 单调栈内的元素顺序、如何取值
    • 栈内元素应该是 top-bottom 递减的,此时向右搜索,找到当前元素大于栈口元素的时候就代表着找到了栈口元素这一列代表的高度的右边界
    • 当前元素大于栈口元素时:
      • 右边界即为当前元素
      • 基准位置即为栈口元素
      • 左边界即是栈口元素的内部相邻元素
  2. 当前元素与栈口元素相等:和接雨水的处理一样
    • 之所以能够对元素值相等的情况有多种处理,是因为在计算中只需要他们代表的值来作为基准高度,而不需要他们的确切下标,利用的下标是左边界和右边界。

对于当前元素与栈口元素的三种比较情况,也和接雨水中的方法无异。

首尾加 0

本题最大的不同就在于需要在输入数组的首尾各加入一个 0,从而解决一些特殊的输入数组:

  • 单调递增数组:heights = [2, 4, 6, 8]

    • 对这样的输入,每一步循环都会将当前下标压入栈。直到遍历结束,也不会有执行计算面积的操作,因为没有碰到一个更小的元素。所以在尾部加入一个 0,可以确保在这种情况下执行正确的面积计算。
  • 单调递减数组:heights = [8, 6, 4, 2]

    • 对这样的输入,每一步循环都会触发面积计算。然而,如上所述,面积的计算需要当前基准高度、左边界、右边界。对第二个下标 1 执行面积计算时,得到右边界 1,基准下标 0。弹出 0 后已经得到了一个空栈,无法得到左边界。所以,这种情况下也不会执行计算面积,因为总是不能得到左边界。
    • 所以在首部加入一个 0,可以确保在这种情况下执行正确的面积计算。

可以看到,在接雨水中我们没有特殊考虑过这两种情况。因为在接雨水中,如果不能够形成一个完整的谷,那么就不需要进行任何计算,也就是说单调递增、递减的数组本来就不该有任何计算结果。而在本题,任何输入都应该正确计算面积,所以不能只计算完整的峰,而要全面考虑。

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        heights.insert(0, 0)
        heights.append(0)

        result = 0
        stack = [0]
        for i in range(1, len(heights)):
            if heights[i] > heights[stack[-1]]:
                stack.append(i)
            elif heights[i] == heights[stack[-1]]:
                stack.pop()
                stack.append(i)
            else:
                while (len(stack) > 0 and heights[i] < heights[stack[-1]]):
                    mid = stack[-1]
                    stack.pop()
                    if len(stack) > 0:
                        left = stack[-1]
                        curr_width = i - left - 1
                        curr_height = heights[mid]
                        result = max(result, curr_height * curr_width)
                stack.append(i)
        return result

双指针

和接雨水一样,本题同样有双指针 + dp 的解法,但是这个解法的时间复杂度有些可疑。
和接雨水相比,本题中的双指针 + dp 会更加复杂一些,因为要求的不再是最大值而是第一个更小值的下标,dp 的递推变得很困难,我也不确定具体的复杂度。

这题的 dp 部分有点像是 KMP,感觉很有意思。

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        # records the index of the first smaller value on the left of i
        left_smaller_idx = [0] * len(heights) 
        left_smaller_idx[0] = -1            # no smaller value on the left, representing non-existence
        for i in range(1, len(heights)):
            temp = i - 1
            while (temp >= 0 and heights[temp] >= heights[i]):
                temp = left_smaller_idx[temp]
            left_smaller_idx[i] = temp
        
        # records the index of the first smaller value on the right of i
        right_smaller_idx = [0] * len(heights) 
        right_smaller_idx[-1] = len(heights)            # no smaller value on the right, representing non-existence
        for i in range(len(heights) - 2, -1, -1):
            temp = i + 1
            while (temp < len(heights) and heights[temp] >= heights[i]):
                temp = right_smaller_idx[temp]
            right_smaller_idx[i] = temp

        result = 0
        for i in range(len(heights)):
            result = max(result, heights[i] * (right_smaller_idx[i] - left_smaller_idx[i] - 1))
        
        return result

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

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

相关文章

高阶数据结构(2)-----红黑树

一)红黑树的基本概念和基本性质: 1)红黑树就是一种高度平衡的二叉搜索树&#xff0c;但是在每一个节点上面都增加了一个存储位来表示结点的颜色&#xff0c;可以是红色或者是黑色&#xff0c;通过对任何一条从根节点到叶子节点上面的路径各个节点着色方式的限制&#xff0c;红黑…

Selenium+Pytest自动化测试框架实战(下)

前言 本文接上篇文章哟。 一、简单学习元素定位 在日常的工作中&#xff0c;我见过很多在浏览器中直接在浏览器中右键Copy Xpath复制元素的同学。这样获得的元素表达式放在 webdriver 中去运行往往是不够稳定的&#xff0c;像前端的一些微小改动&#xff0c;都会引起元素无法…

Truenas scale 安装 Tailscale 内网穿透远程连接SMB服务

起源 没有公网IP&#xff0c;不在同一个路由器&#xff0c;没法远程连接电脑或者服务器。之前一直使用 zerotier&#xff0c; 但是这次使用 Truenas scale 安装 zerotier&#xff0c; 每次重启都变化IP&#xff0c;一直没解决。转投 tailscale。 注册 YouTube有教程&#xf…

基于ssm智能停车场031

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

安装并设置linux虚拟机ubuntu20.04.6 LTS

1 安装虚拟机 1、安装虚拟机模拟软件virtualboxhttps://download.virtualbox.org/virtualboxhttps://download.virtualbox.org/virtualbox/7.0.10/VirtualBox-7.0.10-158379-Win.exe 2、在virtualbox中安装虚拟机ubuntu 20.04.6 LTS 桌面版https://www.releases.ubuntu.com/fo…

进度条--QProgressBar,进度对话框--QProgressDialog

一、QProgressBar 进度条 1、QProgressBar 类继承自 QWidget&#xff0c;它是一个 QWidget 部件&#xff0c; QProgressBar 除了将其放置 于进度对话框之中外&#xff0c;还可将其放置于窗口的状态栏等其他部件中。 QProgressBar提供了一个水平或垂直的进度条&#xff0c;可以…

JDBC基本概念

什么是JDBC JDBC概念 JDBC&#xff08;Java DataBase Connectivity&#xff09;是一套统一的基于Java语言的关系数据库编程接口规范。 该规范允许将SQL语句作为参数通过JDBC接口发送给远端数据库&#xff0c; …

8位和32位单片机如何选择适合,以及主要区别!

单片机直接影响到项目的成功和性能&#xff0c;我们将分享如何选择适合您的应用的8位或32位单片机。 8位单片机 vs. 32位单片机&#xff1a; 一、性能和处理能力&#xff1a; 8位单片机&#xff1a; 8位单片机通常适用于相对简单的应用&#xff0c;如传感器控制、LED显示、小…

代码随想录算法训练营第三十五天| 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球

860.柠檬水找零 本题看上好像挺难&#xff0c;其实挺简单的&#xff0c;大家先尝试自己做一做。 代码随想录 public boolean lemonadeChange(int[] bills) {int five 0;int ten 0;for (int i 0; i < bills.length; i) {if (bills[i] 5) {five;} else if (bills[i] 10)…

Mysql同步数据到Doris的踩坑过程

问题背景 由于项目需要&#xff0c;需要把多个Mysql数据库的数据同步到Doris数据库&#xff0c;然后利用Doris强调的计算和查询能力&#xff0c;来满足业务需求。有关Doris可以查看它的官方文档来了解它。 seatunnel的使用到放弃 缘起 从《第十届GIAC全球互联网架构大会》了…

论如何在Android中还原设计稿中的阴影

每当设计稿上注明需要添加阴影时&#xff0c;Android上总是显得比较棘手&#xff0c;因为Android的阴影实现方式与Web和iOS有所区别。 一般来说阴影通常格式是有&#xff1a; X: 在X轴的偏移度 Y: 在Y轴偏移度 Blur: 阴影的模糊半径 Color: 阴影的颜色 何为阴影 但是在A…

手刻 Deep Learning -第壹章 -PyTorch教学-激励函数与感知机入门(上)

一、前言 本文接续前篇教学 Pytorch 与线性回归 &#xff0c;本文着重在 Activation Function &#xff08; 中文称 激励函数 &#xff09;&#xff0c;我们会介绍激励函数 &#xff08;也有人称 激活函数&#xff1f; 激发函数&#xff1f; &#xff09; 为什么会有用&#xf…

Python 06 之面向对象基础

&#x1f600;前言 在日常编程和软件开发中&#xff0c;我们通常会遇到各种各样的问题&#xff0c;其中很多问题都可以通过面向对象的程序设计方法来解决。面向对象编程不仅可以使代码更加组织化和系统化&#xff0c;而且还可以提高代码的重用性和可维护性。 . 在本教程中&…

一个工位的演讲

前几天&#xff0c;知乎官方制作了一个视频&#xff0c;感觉这个视频非常不错&#xff0c;推荐给大家看看。 这个短片很有创意&#xff0c;而且&#xff0c;内容也很丰富。 为什么说这个短片很有创意呢&#xff1f;因为它是从一个工位的角度切入的&#xff0c;所谓铁打的工位&a…

基于matlab实现的电力系统稳定性分析摆幅曲线代码

完整程序&#xff1a; clear; clc; t 0; tf 0; tfl 0.5; tc 0.5; % tc 0.05, 0.125, 0.5 sec for 2.5 cycles, 6.25 cycles & 25 cycles resp ts 0.05; m 2.52 / (180 * 50); i 2; dt 21.64 * pi / 180; ddt 0; time(1) 0; ang(1) 21.64; pm 0.9; pm1 2.44;…

解锁大数据宝藏:使用AI预测未来趋势的新方法

文章目录 大数据的价值传统方法与AI的优势使用AI预测未来趋势的新方法1. 时间序列分析2. 自然语言处理&#xff08;NLP&#xff09;3. 预测市场趋势 应用前景与挑战应用前景挑战和限制 结论 &#x1f389;欢迎来到AIGC人工智能专栏~解锁大数据宝藏&#xff1a;使用AI预测未来趋…

软件设计师考试学习1

前言 计算机组成原理及体系结构 数据的表示 进制的转换 原码反码补码移码 最高位是符号位&#xff0c;负数符号位为1 反码补码正数和原码一样&#xff0c;负数有区别 反码符号位不动&#xff0c;其他位置取反 补码在反码基础上加1 移码是将补码的符号为取反 在原码和反码中…

Sqlserver如何调试存储过程

前提&#xff1a;需要使用Sql Server Managerment Studio 工具进行调试。 步骤&#xff1a; 1.选择存储过程&#xff0c;右键选择“执行存储过程”。操作过后&#xff0c;会生成一个调用存储过程的代码块。 2.以编辑模式打开所以需要调试的存储过程。 3.点击调试按钮进行调…

k8s集群使用ingress转发grafana服务

文章目录 前言一、思路二、grafana准备1. grafana-configmap.yaml2. grafana.yaml 三、ingress准备1. ingress.yaml2. grafana-externalname.yaml3. ingress-nginx-controller 四、 本机host文件准备五、访问测试 前言 在k8s集群中&#xff0c;使用ingress服务转发grafana的页…

苹果是真牛,数据线的钱要赚,换电池钱也要赚,贪婪成性

iPhone15发布会是苹果当前的热点&#xff0c;发布会结束后苹果又传出了一个消息&#xff0c;进一步提高更换电池的价格&#xff0c;显示出苹果意图进一步割韭菜&#xff0c;提升利润&#xff0c;这就有点贪婪成性了吧&#xff1f; 据了解 iPhone 7、8 及 SE 系列由 528 元涨至 …