【力扣】84. 柱状图中最大的矩形 <模拟、双指针、单调栈>

目录

    • 【力扣】84. 柱状图中最大的矩形
    • 题解
        • 暴力求解
        • 双指针
        • 单调栈

【力扣】84. 柱状图中最大的矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。

示例 1:
在这里插入图片描述

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

示例 2:
在这里插入图片描述

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

提示:
1 <= heights.length <= 1 0 5 10^5 105
0 <= heights[i] <= 1 0 4 10^4 104

题解

暴力求解

public static int largestRectangleArea(int[] heights) {
    int sum = 0;
    for (int i = 0; i < heights.length; i++) {
        int left = i;
        int right = i;

        //找当前遍历元素之前第一个比它小的元素
        while (left >= 0) {
            if (heights[left] < heights[i]) {
                break;
            }
            left--;
        }

        //找当前遍历元素之后第一个比它小的元素
        while (right < heights.length) {
            if (heights[right] < heights[i]) {
                break;
            }
            right++;
        }

        int w = right - left - 1;
        int h = heights[i];
        sum = Math.max(sum, w * h);
    }
    return sum;
}

双指针

public class Solution {
    public static int largestRectangleArea(int[] heights) {
        int[] minLeftIndex = new int[heights.length];
        int[] minRightIndex = new int[heights.length];


        // 记录左边第一个小于该柱子的下标
        minLeftIndex[0] = -1;
        for (int i = 1; i < heights.length; i++) {
            int t = i - 1;
            // 这里不是用if,而是不断向右寻找的过程
            while (t >= 0 && heights[t] >= heights[i]) {
                t = minLeftIndex[t];
            }
            minLeftIndex[i] = t;
        }


        // 记录每个柱子右边第一个小于该柱子的下标
        minRightIndex[heights.length - 1] = heights.length;
        for (int i = heights.length - 2; i >= 0; i--) {
            int t = i + 1;
            while (t < heights.length && heights[t] >= heights[i]) {
                t = minRightIndex[t];
            }
            minRightIndex[i] = t;
        }

        /*for (int a : minLeftIndex) {
            System.out.println(a);
        }
        System.out.println("______________________________");

        for (int a : minRightIndex) {
            System.out.println(a);
        }*/

        // 求和
        int result = 0;
        for (int i = 0; i < heights.length; i++) {
            int sum = heights[i] * (minRightIndex[i] - minLeftIndex[i] - 1);
            result = Math.max(sum, result);
        }
        return result;
    }

    public static void main(String[] args) {
        int[] heights = {2, 4, 2};
        System.out.println(largestRectangleArea(heights));
    }
}

单调栈

注意:单调栈是递减的

class Solution {
    int largestRectangleArea(int[] heights) {
        Stack<Integer> st = new Stack<Integer>();
        
        // 数组扩容,在头和尾各加入一个元素,防止只递增或者只递减的数组
        int [] newHeights = new int[heights.length + 2];
        newHeights[0] = 0;
        newHeights[newHeights.length - 1] = 0;
        for (int index = 0; index < heights.length; index++){
            newHeights[index + 1] = heights[index];
        }

        heights = newHeights;
        
        st.push(0);
        int result = 0;
        // 第一个元素已经入栈,从下标1开始
        for (int i = 1; i < heights.length; i++) {
            // 注意heights[i] 是和heights[st.top()] 比较 ,st.top()是下标
            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.peek();
                    st.pop();
                    int left = st.peek();
                    int right = i;
                    int w = right - left - 1;
                    int h = heights[mid];
                    result = Math.max(result, w * h);
                }
                st.push(i);
            }
        }
        return result;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用ChatGPT进行创意写作的缺点

Open AI警告ChatGPT的使用者要明白此工具的局限性&#xff0c;更不应完全依赖。作为一位创作者&#xff0c;这一点非常重要&#xff0c;应尽可能地避免让版权问题或不必要的文体问题出现在自己的作品中。[1] 毕竟使用ChatGPT进行创意写作目前还有以下种种局限或缺点[2]&#xf…

5.5.webrtc的线程管理

今天呢&#xff0c;我们来介绍一下线程的管理与绑定&#xff0c;首先我们来看一下web rtc中的线程管理类&#xff0c;也就是thread manager。对于这个类来说呢&#xff0c;其实实现非常简单&#xff0c;对吧&#xff1f; 包括了几个重要的成员&#xff0c;第一个成员呢就是ins…

学习笔记230804---逻辑跳转this.$router.push在写法上的优化

今天和资深前端代码写重&#xff0c;同时写页面带参跳转&#xff0c;组长觉得他写的方式比我高端一点&#xff0c;我觉得确实是&#xff0c;像资深大佬学习。 我的写法&#xff1a; this.$router.push(/bdesign?applicationId${this.data.id}&appName${this.data.name})…

[VS/C++]如何更好的配置DLL项目中的成品输出

注意&#xff0c;解决方案与项目不放在同一个文件夹中&#xff0c;即不选中图中选项 直入主题 首先右键项目选择属性&#xff0c;或者选中项目然后AltEnter 选择配置属性下的常规 分别在四种配置中编辑输出目录如下 注意&#xff0c;四种配置要分别配置&#xff0c;一个个来…

一百六十一、Kettle——Linux上安装的kettle9.2开启carte服务(亲测、附流程截图)

一、目的 在Linux上安装好kettle9.2并且连接好各个数据库后&#xff0c;下面开启carte服务 二、实施步骤 &#xff08;一&#xff09;carte服务文件路径 kettle的Linux运行的carte服务文件是carte.sh &#xff08;二&#xff09;修改kettle安装路径下的pwd文件夹里的服务器…

Netty+springboot开发即时通讯系统笔记(四)终

实时性 1.线程池多线程&#xff0c;把消息同步给其他端和对方用户&#xff0c;其中数据持久化往往是最浪费时间的操作&#xff0c;可以使用mq异步存储&#xff0c;因为其他业务不需要拿着整条数据&#xff0c;只需要这条数据的id进行操作。 2。消息校验前置&#xff0c;放在t…

谷歌推出首款量子弹性 FIDO2 安全密钥

谷歌在本周二宣布推出首个量子弹性 FIDO2 安全密钥&#xff0c;作为其 OpenSK 安全密钥计划的一部分。 Elie Bursztein和Fabian Kaczmarczyck表示&#xff1a;这一开源硬件优化的实现采用了一种新颖的ECC/Dilithium混合签名模式&#xff0c;它结合了ECC抵御标准攻击的安全性和…

机器学习与模式识别3(线性回归与逻辑回归)

一、线性回归与逻辑回归简介 线性回归主要功能是拟合数据&#xff0c;常用平方误差函数。 逻辑回归主要功能是区分数据&#xff0c;找到决策边界&#xff0c;常用交叉熵。 二、线性回归与逻辑回归的实现 1.线性回归 利用回归方程对一个或多个特征值和目标值之间的关系进行建模…

java版本spring cloud 企业工程系统管理 工程项目管理系统源码em

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff…

消息中间件的选择:RabbitMQ是一个明智的选择

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; MQ&#xff08;Message Queue&#xff09; MQ&#xff08;消息队列&#xff09;是一种用于在应用程序之间进行异步通信的技术&#xff1b;允许应用程序通过发送和接收…

Vue3 用父子组件通信实现页面页签功能

一、大概流程 二、用到的Vue3知识 1、组件通信 &#xff08;1&#xff09;父给子 在vue3中父组件给子组件传值用到绑定和props 因为页签的数组要放在父页面中&#xff0c; data(){return {tabs: []}}, 所以顶部栏需要向父页面获取页签数组 先在页签页面中定义props用来接…

CloudCompare——统计滤波

目录 1.统计滤波2.软件实现3.完整操作4.算法源码5.相关代码 本文由CSDN点云侠原创&#xff0c;CloudCompare——统计滤波&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫。 1.统计滤波 算法原理见&#xff1a;PCL 统计滤波器…

Cpp学习——类与对象3

目录 一&#xff0c;初始化列表 1.初始化列表的使用 2.初始化列表的特点 3.必须要使用初始化列表的场景 二&#xff0c;单参数构造函数的隐式类型转换 1.内置类型的隐式类型转换 2. 自定义类型的隐式类型转换 3.多参数构造函数的隐式类型转换 4.当你不想要发生隐式类型转换…

CPU缓存一致性原理

CPU缓存一致性原理 在本站的文章CPU缓存那些事儿中&#xff0c; 介绍了cpu的多级缓存的架构和cpu缓存行cache line的结构。CPU对于缓存的操作包含读和写&#xff0c;读操作在cache line中有所涉及&#xff0c;在本文中&#xff0c;将重点讨论CPU对于缓存进行写时的行为。 单核…

美国大模型风向速报(一)为何重视提示工程?LangChain+向量数据库+开源大模型真香...

多家&#xff0c;且独家来自美国的信源同时向“亲爱的数据”表示&#xff0c; 提示工程&#xff08;Prompt Engineering&#xff09;在美国大模型领域备受重视。 读者都要聊&#xff0c; 那就干活。 &#xff08;一&#xff09;开源真香 现阶段&#xff0c;AI开源极客大展身手&…

【视觉SLAM入门】5.2. 2D-3D PNP 3D-3D ICP BA非线性优化方法 数学方法SVD DLT

"养气之学&#xff0c;戒之躁急" 1. 3D-2D PNP1.1 代数法1.1.1 DLT(直接线性变换法)1.1.2. P3P 1.2 优化法BA (Bundle Adjustment)法 2. 3D-3D ICP2.1 代数法2.1.1 SVD方法 2.2 优化(BA)法2.2.2 非线性优化方法 前置事项&#xff1a; 1. 3D-2D PNP 该问题描述为&am…

线性代数的学习和整理7:各种特殊矩阵(草稿-----未完成)

目录 1 单位矩阵 为什么单位矩阵I是 [1,0;0,1]T 而不是[1,1;1,1]T 2 旋转矩阵 3 伸缩矩阵 放大缩小倍数矩阵 4 镜像矩阵 5 剪切矩阵 矩阵 行向量 列向量 方阵 1 单位矩阵 [ 1 0 0 1] 为什么单位矩阵I是 [1,0;0,1]T 而不是[1,1;1,1]T 因为 矩阵 [1,0;0,1] 代表…

websocket + stomp + sockjs学习

文章目录 学习链接后台代码引入依赖application.ymlWebSocketConfigPrivateControllerWebSocketService WebSocketEventListenerCorsFilter 前端代码Room.vue 学习链接 WebSocket入门教程示例代码&#xff0c;代码地址已fork至本地gitee&#xff0c;原github代码地址&#xff…

马哈鱼数据血缘工具背后的项目: gsp_demo_java 项目简单介绍与使用

0.背景 马哈鱼数据血缘工具(https://www.sqlflow.cn/)是SQLflow工具的中文译名,实际就是sqlflow. 对于SQL flow来说,底层调用的是General SQL Parser(GSP https://sqlparser.com) 的库. 这个gsp有开源的java demo项目:https://github.com/sqlparser/gsp_demo_java 1.快速使用…

【C# 基础精讲】LINQ 基础

LINQ&#xff08;Language Integrated Query&#xff09;是一项强大的C#语言特性&#xff0c;它使数据查询和操作变得更加简洁、灵活和可读性强。通过使用LINQ&#xff0c;您可以使用类似SQL的语法来查询各种数据源&#xff0c;如集合、数组、数据库等。本文将介绍LINQ的基础概…