力扣第84 题柱状图中最大的矩形 C++ 单调栈 Java

news2024/10/6 22:30:05

题目

84. 柱状图中最大的矩形

困难

相关标签

栈   数组   单调栈

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

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

示例 1:

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

示例 2:

输入: heights = [2,4]
输出: 4

提示:

  • 1 <= heights.length <=105
  • 0 <= heights[i] <= 104

思路和解题方法

  1. int result = 0;:初始化结果变量为0,用来存放最大矩形面积。
  2. stack<int> st;:声明一个整型栈st,用来存放数组元素的下标。
  3. heights.insert(heights.begin(), 0);:在heights数组头部插入一个值为0的元素。
  4. heights.push_back(0);:在heights数组尾部插入一个值为0的元素。
  5. st.push(0);:将0这个下标入栈。

接下来是for循环,遍历heights数组:

  1. for (int i = 1; i < heights.size(); i++):从下标1开始遍历heights数组。
  2. if (heights[i] > heights[st.top()]):如果当前高度大于栈顶元素所对应的高度,则将当前下标入栈。
  3. else if (heights[i] == heights[st.top()]):如果当前高度等于栈顶元素所对应的高度,则不做任何操作。
  4. else:如果当前高度小于栈顶元素所对应的高度,进入循环。
  5. while (!st.empty() && heights[i] < heights[st.top()]):当栈不为空且当前高度小于栈顶元素所对应的高度时,执行循环。
  6. int mid = st.top(); st.pop();:取出栈顶元素的下标,并将其出栈。
  7. if (!st.empty()):如果栈不为空,说明存在左边界。
  8. int left = st.top(); int right = i;:获取左边界和右边界的下标。
  9. int w = right - left - 1; int h = heights[mid];:计算矩形的宽度和高度。
  10. result = max(result, w * h);:更新最大矩形面积。

最后,返回计算得到的最大矩形面积result。

复杂度

        时间复杂度:

                O(n)

时间复杂度为O(n),其中n是输入数组heights的长度。因为在一次遍历中,每个元素最多被压入和弹出栈各一次,所以总的操作次数与输入数组的长度成线性关系。

        空间复杂度

                O(n)

空间复杂度为O(n),主要是由栈st所使用的额外空间造成的。

c++ 代码


class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int result = 0; // 初始化最大面积为0
        stack<int> st; // 定义一个栈来辅助计算
        heights.insert(heights.begin(), 0); // 数组头部加入元素0
        heights.push_back(0); // 数组尾部加入元素0
        st.push(0); // 将0入栈作为起始位置

        // 从下标1开始遍历数组
        for (int i = 1; i < heights.size(); i++) {
            if (heights[i] > heights[st.top()]) { // 情况一:当前高度大于栈顶高度,入栈
                st.push(i);
            } else if (heights[i] == heights[st.top()]) { // 情况二:当前高度等于栈顶高度,可以忽略
                st.pop(); // 这个可以加,可以不加,效果一样,思路不同
                st.push(i);
            } else { // 情况三:当前高度小于栈顶高度,需要计算面积并更新最大面积
                while (!st.empty() && heights[i] < heights[st.top()]) { // 注意是while
                    int mid = st.top(); // 弹出栈顶元素作为矩形的高度
                    st.pop();
                    if (!st.empty()) {
                        int left = st.top(); // 获取左边界
                        int right = i; // 获取右边界
                        int w = right - left - 1; // 计算宽度
                        int h = heights[mid]; // 获取高度
                        result = max(result, w * h); // 更新最大面积
                    }
                }
                st.push(i); // 将当前位置入栈
            }
        }
        return result; // 返回最大面积
    }
};

简洁代码

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int> st; // 创建一个整型栈st,用来存放数组元素的下标
        heights.insert(heights.begin(), 0); // 在heights数组头部插入一个值为0的元素
        heights.push_back(0); // 在heights数组尾部插入一个值为0的元素
        st.push(0); // 将0这个下标入栈
        int result = 0; // 初始化结果变量为0,用来存放最大矩形面积
        for (int i = 1; i < heights.size(); i++) { // 遍历heights数组
            while (heights[i] < heights[st.top()]) { // 当当前高度小于栈顶元素所对应的高度时,执行循环
                int mid = st.top();
                st.pop(); // 取出栈顶元素的下标,并将其出栈
                int w = i - st.top() - 1; // 计算矩形的宽度
                int h = heights[mid]; // 获取矩形的高度
                result = max(result, w * h); // 更新最大矩形面积
            }
            st.push(i); // 将当前下标入栈
        }
        return result; // 返回计算得到的最大矩形面积
    }
};

Java代码

class Solution {
    public int largestRectangleArea(int[] heights) {
        // 创建一个新数组newHeight,长度比原数组heights多2,并在两端补0
        int[] newHeight = new int[heights.length + 2];
        System.arraycopy(heights, 0, newHeight, 1, heights.length); // 复制heights数组到newHeight数组
        newHeight[heights.length+1] = 0; // 在newHeight数组末尾加入一个值为0的元素
        newHeight[0] = 0; // 在newHeight数组头部加入一个值为0的元素

        Stack<Integer> stack = new Stack<>(); // 创建一个整型栈stack,用来存放数组元素的下标
        stack.push(0); // 将0这个下标入栈

        int res = 0; // 初始化结果变量为0,用来存放最大矩形面积
        for (int i = 1; i < newHeight.length; i++) { // 遍历newHeight数组
            while (newHeight[i] < newHeight[stack.peek()]) { // 当当前高度小于栈顶元素所对应的高度时,执行循环
                int mid = stack.pop(); // 取出栈顶元素的下标,并将其出栈
                int w = i - stack.peek() - 1; // 计算矩形的宽度
                int h = newHeight[mid]; // 获取矩形的高度
                res = Math.max(res, w * h); // 更新最大矩形面积
            }
            stack.push(i); // 将当前下标入栈
        }
        return res; // 返回计算得到的最大矩形面积
    }
}

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

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

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

相关文章

人工智能基础_机器学习032_多项式回归升维_原理理解---人工智能工作笔记0072

现在开始我们来看多项式回归,首先理解多维 原来我们学习的使用线性回归,其实就是一条直线对吧,那个是一维的,我们之前学的全部都是一维的对吧,是一维的,然后是多远的,因为有多个x1,x2,x3,x4... 但是比如我们有一个数据集,是上面这种,的如果用一条直线很难拟合,那么 这个时候,…

贪吃蛇游戏和俄罗斯方块

一、创建新项目 创建一个新的项目&#xff0c;并命名。 创建一个名为images的文件夹用来存放游戏相关图片。 然后再在项目的src文件下创建一个com.xxx.view的包用来存放所有的图形界面类&#xff0c; 创建一个com.xxx.controller的包用来存放启动的入口类(控制类) package …

多svn仓库一键更新脚本分享

之前分享过多git仓库一键更新脚本&#xff0c;本期就分享下svn仓库的一键更新脚本 1、首先需要设置svn为可执行命令行 打开SVN安装程序&#xff0c;选择modify&#xff0c;然后点击 command client tools&#xff0c;安装命令行工具 2、update脚本 echo 开始更新SVN目录&…

Uniapp-小程序自定义导航栏

一、项目背景 制作小程序页面时候发现原生导航栏有一定的高度是没有背景渲染的会出现这种情况 但是我们需要的是 二、原因 小程序的原生导航栏存在。一般可以使用 纯色填充顶部栏 可以直接使用navigationBarBackgroundColor完成 在style中添加 "navigationBarBackgrou…

一文图解爬虫_姊妹篇(spider)

—引导语 爬虫&#xff0c;没有一个时代比当前更重视它。一个好的爬虫似乎可以洞穿整个互联网&#xff0c;“来装满自己的胃”。 接上一篇&#xff1a;一文图解爬虫&#xff08;spider&#xff09; 博主已初步对爬虫的“五脏六腑”进行了解剖。虽然俗称“爬虫”&#xff0c;但窃…

[C国演义] 第十九章

第十九章 回文子串最长回文子串 子串, 等价于 子数组, 都要求连续 回文子串 力扣链接 子串 ⇒ 状态表示 子串 ⇒ 状态转移方程 初始化 : 全都初始化为 false 遍历顺序 返回结果 : 此时的dp表中, 已经是每个区间能否是回文子串的结果了 ⇒ 我们要统计所有的回文子串的…

PDF文件标题修改方法

目录 一、PDF文件的标题和名称 二、标题修改方法 1.浏览器打开PDF Editor Free网站 2.点击Free Oline 3.选择第三个从本地上传PDF附件 4.将附件上传&#xff0c;两种方法都可以​编辑 5.等待加载&#xff0c;附件大的情况下会有些慢&#xff0c;耐心等待即可 6. 导入文…

PyG(torch_geometric)的MessagePassing详解

1. 提出MessagePassing的目的 MessagePassing是图神经网络&#xff08;Graph Neural Networks&#xff0c;GNNs&#xff09;的一个基础组件&#xff0c;它被设计用来处理图形数据的问题。在图形数据中&#xff0c;数据点&#xff08;节点&#xff09;之间的关系&#xff08;边…

openGauss学习笔记-123 openGauss 数据库管理-设置账本数据库-账本数据库概述

文章目录 openGauss学习笔记-123 openGauss 数据库管理-设置账本数据库-账本数据库概述123.1 背景信息123.2 操作步骤 openGauss学习笔记-123 openGauss 数据库管理-设置账本数据库-账本数据库概述 123.1 背景信息 账本数据库融合了区块链思想&#xff0c;将用户操作记录至两…

服务号转订阅号如何操作

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;一、文章推送的篇数不同服务号在文章的推送篇数上是有所限制的&#xff08;每月推4次&#xff09;订阅号则每天可推送一篇文章。二、定义不同服务号主要是为关注用户提供服务使用的&#xff1b;订阅…

【仿真动画】ABB IRB 8700 机器人搬运(ruckig在线轨迹生成)动画欣赏

场景 动画 一、IRB 8700简介 二、动画脚本重点分析 2.1 sim.moveToPose 通过在两个 poses 之间执行插值&#xff0c;使用 Ruckig 在线轨迹生成器生成对象运动数据。该函数可以通过处理 4 个运动变量&#xff08;x、y、z 和两个姿势之间的角度&#xff09;或单个运动变量&#…

服务器数据恢复—VMware虚拟化下误操作导致服务器崩溃的数据恢复案例

服务器故障&分析&#xff1a; VMware虚拟化&#xff0c;vmfs文件系统&#xff0c;共3块磁盘。工作人员误操作将VMware虚拟化重装系统&#xff0c;服务器崩溃。 正常情况下&#xff0c;重装系统会导致文件系统元文件被覆盖。要恢复数据须找到重装系统前的文件系统残留信息并…

操作系统(二 )| 进程控制 进程状态 进程描述 进程控制 进程同步互斥

文章目录 1 进程和程序区别2 进程状态2.1 进程的5种基本状态2.2 进程状态之间转换2.3 七状态模型 3 进程描述3.1 进程控制块 PCB3.2 进程块组织方式 4 进程控制5 进程同步 互斥5.1 区分进程互斥和同步5.2 核心方案5.3 其他方案方案1 设置锁变量方案2 严格轮转法方案3 Peterson解…

003.文件描述符、重定向

1、文件描述符 文件描述符是与输入和输出流相关联的整数。最广为人知的文件描述符是stdin、stdout和stderr。我们可以将某个文件描述符的内容重定向到另一个文件描述符中。 在编写脚本的时候会频繁用到标准输入&#xff08;stdin&#xff09;、标准输出&#xff08;stdout&am…

图像分类:弥合像素和理解之间的差距

一、介绍 在人工智能的广阔领域中&#xff0c;图像分类作为一种关键应用脱颖而出&#xff0c;它无缝地融合了计算机视觉和机器学习的复杂性。图像分类的核心是训练机器对数字图像中的对象或场景进行识别和分类。这项技术有着广泛的应用&#xff0c;从自动驾驶汽车和医疗诊断到社…

Spring-Spring之AOP底层源码解析(下)

ProxyFactory选择cglib或jdk动态代理原理 ProxyFactory在生成代理对象之前需要决定到底是使用JDK动态代理还是CGLIB技术&#xff1a; // config就是ProxyFactory对象// optimize为true,或proxyTargetClass为true,或用户没有给ProxyFactory对象添加interface if (config.isOpt…

CNVD-2021-09650:锐捷NBR路由器(guestIsUp.php)RCE漏洞复现 [附POC]

文章目录 锐捷NBR路由器guestIsUp.php远程命令执行漏洞(CNVD-2021-09650)复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 锐捷NBR路由器guestIsUp.php远程命令执行漏洞(CNVD-2021-09650)复现 [附POC] 0x01 前言 免…

解决 requests 库上传大文件速度慢的问题:从问题原因到解决方案

提要&#xff1a;本文将 深入探讨 requests 库上传大文件速度慢的问题&#xff0c;并提出相应的解决方案。 通过本文&#xff0c;您可以了解到 requests 库上传大文件的原理&#xff0c;了解问题的原因并找到解决方案。 最后&#xff0c;我们将 探讨如何优化上传大文件的处理速…

每日一题 2656. K 个元素的最大和(简单)

感觉每日一题除了困难之外很久没有做到有营养的题了 class Solution:def maximizeSum(self, nums: List[int], k: int) -> int:return (2 * max(nums) k - 1) * k // 2

二叉树(进阶)

文章目录 1.内容安排说明2. 二叉搜索树2.1二叉搜索树的概念2.2二叉搜索树的实现2.3二叉树的性能&#xff1a; 搜索二叉树的应用k 模型kv模型 1.内容安排说明 二叉树在前面c数据结构阶段&#xff1b;已经讲过了&#xff1b;本节取名二叉树进阶的原因是&#xff1a; 1.map和set特…