【单调栈】下一个更大元素 I

news2024/11/17 19:44:05

文章目录

  • Tag
  • 题目来源
  • 题目解读
  • 解题思路
    • 方法一:暴力枚举
    • 方法二:单调栈+哈希表
  • 知识回顾
    • 单调栈
  • 写在最后

Tag

【单调栈+哈希表】【数组】


题目来源

496. 下一个更大元素 I


题目解读

找出 nums1 中数字 xnums2 中的位置,并找出在 nums2 中比 x 右侧的第一个比 x 大的元素。


解题思路

方法一:暴力枚举

本题的数据规模为 1 0 3 10^3 103,暴力枚举的时间复杂度为 1 0 6 10^6 106,暴力的方法可以通过。

两层循环,第一层枚举数组 nums1 中的 x

  • 第二层枚举,先使用 while 循环找到在 nums2 中的 x
  • 再在 x 的右侧找比 x 大的第一个元素,找不到就将 -1 作为答案。

实现代码

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size();
        vector<int> res(m, -1);
        for (int i = 0; i < m; ++i) {
            int j = 0;
            int x = nums1[i];
            while (j < n && nums2[j] != x) {
                ++j;
            }
            for (int k = j + 1; k < n; ++k) {
                if (nums2[k] > x) {
                    res[i] = nums2[k];
                    break;
                }
            }
        }
        return res;
    }
};

复杂度分析

时间复杂度: O ( m n ) O(mn) O(mn) m m m 为数组 nums1 的长度, n n n 为数组 nums2 的长度。

空间复杂度: O ( 1 ) O(1) O(1),作为返回答案的数组 res 不算作额外的空间。

方法二:单调栈+哈希表

我们可以计算 nums2 中的每一个元素右侧的更大元素,然后将元素与更大的元素存储在哈希表 hashMap中,最后遍历 nums1 中的 x,查找 x 在哈希表中对应的值,这样查询的时间复杂度为 O ( m ) O(m) O(m) m m m 为数组 nums1 的长度。

计算 nums2 中的每一个元素右侧的更大元素,我们可以使用暴力枚举的方法,这样的时间复杂度为 O ( n 2 ) O(n^2) O(n2) n n n 为数组 nums2 的长度,也有时间复杂度为 O ( n ) O(n) O(n) 的方法。

O ( n 2 ) O(n^2) O(n2) 计算 hashMap

暴力枚举的方法很简单,直接上代码。

int n = nums2.size();
unordered_map<int, int> hashMap;
for (int i = 0; i < n; ++i) {
    int j = i + 1;
    // 找到大于nums1[i] 的第一个元素或者越界
    while (j < n && nums2[j] <= nums1[i]) {
        ++j;
    }
    // 如果越界了,更新值为 -1,否则表示找到了大于 nums1[i] 的第一个元素
    hashMap[nums1[i]] = j < n ? nums2[j] : -1;
}

O ( n ) O(n) O(n) 计算 hashMap

维护一个单调栈 stk,栈中元素值从栈底到栈顶是依次递增的。

我们从后向前枚举数组 nums2 来更新 hashMap 以及单调栈 stk(也可以从前往后枚举数组来更新 hashMap,后面会贴上代码):

  • 将当前枚举的元素值 nums2[i] 与栈顶的元素比较,如果栈非空并且栈顶的元素值小于或者等于 nums2[i],就出栈,直到栈为空或者找到比 nums2[i] 的栈中元素;
  • 如果栈为空了,说明 nums2[i] 右侧没有比它大的元素,更新哈希表 hashMap[num2[i]] = -1;否则就是找到了nums2[i] 右侧比它大的元素了;
  • nums2[i] 加入栈中。

实现代码如下:

unordered_map<int, int> hashMap;      // 存放元素的下一个更大元素
for(i = nums2.size()-1; i >= 0; --i){
    int num = nums2[i];
    while(!stk.empty() && num >= stk.top()){
        stk.pop();
    }
    hashMap[num] = stk.empty() ? -1 : stk.top();
    stk.push(num);
}

O ( n ) O(n) O(n) 时间复杂度更新 hashMap 的方法以及哈希表更新答案数组 ans 的方法是本题最优的方法,总的实现代码如下:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        unordered_map<int, int> hashMap;      // 存放元素的下一个更大元素
        stack<int> stk;
        int i;
        int n = nums1.size();
        vector<int> ans(n);
        for(i = nums2.size()-1; i >= 0; --i){
            int num = nums2[i];
            while(!stk.empty() && num >= stk.top()){
                stk.pop();
            }
            hashMap[num] = stk.empty() ? -1 : stk.top();
            stk.push(num);
        }
        
        for(i = 0; i < n; ++i){
            ans[i] = hashMap[nums1[i]];
        }
        return ans;
    }
};

从后向前枚举更新 hashMap

直接贴上代码

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        unordered_map<int, int> hashtable;      // 存放对应元素的下一个更大元素
        stack<int> stk;
        for(int i = 0; i < nums2.size(); ++i){
            int num = nums2[i];
            while(!stk.empty() && stk.top() < num){
                hashtable[stk.top()] = num;
                stk.pop();
            }
            stk.push(num);
        }
        
        int n = nums1.size();
        vector<int> ans(n, -1);
        for(int i = 0; i < n; ++i){
            if (hashtable.find(nums1[i]) != hashtable.end()) {
                ans[i] = hashtable[nums1[i]];
            }
        }
        return ans;
    }
};

复杂度分析

时间复杂度: O ( m + n ) O(m+n) O(m+n) m m m 为数组 nums1 的长度, n n n 为数组 nums2 的长度。 我们需要遍历 nums2 以计算 nums2 中每个元素右边的第一个更大的值,对应的时间复杂度为 O ( n ) O(n) O(n);需要遍历 nums1 以生成查询结果,对应的时间复杂度为 O ( m ) O(m) O(m)

空间复杂度: O ( n ) O(n) O(n),使用哈希表的额外空间开销。


知识回顾

单调栈

栈是一种比较常用的基本数据结构,我们使用栈的性质可以解决一些 “后进先出” 的问题。

有别于栈的是,单调栈里的元素是有序的。单调栈按栈内元素的递增、递减顺序分为单调递增栈和单调递减栈。但是查询了一些资料之后没有发现明确的单调递增栈(单调递减栈)定义。有的是说,从栈底到栈顶的元素按照递增次序的是单调递增栈,而有的说法相反。这里也就不纠结了,也没有一个官方的说法。自己在使用的时候自己明确就好,有的题目要求使用到的话题目会说清楚的。

【每日一题】股票价格跨度
【单调栈】下一个更大元素 II
【单调栈】下一个更大元素 III

通过本题以及以上几个例题的学习,我们进行一些小小的总结:下一个/上一个更大、更小的值,基本上都可以使用【单调栈】来解决。

写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

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

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

相关文章

【SpringBoot】文件分片上传、合并

背景 在上传大型文件时&#xff0c;一般采用的都是分片、断点续传等技术&#xff0c;这样不会导致因文件过大而造成系统超时或者过压等情况。 接下来我们进入教学 如果有帮助到您&#xff0c;麻烦请点击个收藏、赞&#xff0c;谢谢~ 一、实际效果图 整个前端网页的效果图&…

商城小程序代客下单程序开发演示

一款专为传统电商、实体商家开发的商城系统小程序&#xff0c;做私域、做留存、做社交必备功能全都有。 1、丰富的营销玩法&#xff1a;拼团、秒杀、定金预售、分销、社区团购、积分商城、支付有礼等主流获客玩法都有。 2、强大的会员体系&#xff1a;普通会员、付费会员、会…

spring 事务源码阅读

开启事务 使用EnableTransactionManagement注解开启事务 该注解会引入TransactionManagementConfigurationSelector类&#xff0c;然后该类导入两个类AutoProxyRegistrar和ProxyTransactionManagementConfiguration。 1、添加bean后置处理器 AutoProxyRegistrar类的作用是注…

883. 高斯消元解线性方程组

883. 高斯消元解线性方程组 - AcWing题库 输入一个包含 n 个方程 n 个未知数的线性方程组。 方程组中的系数为实数。 求解这个方程组。 下图为一个包含 m 个方程 n 个未知数的线性方程组示例&#xff1a; 输入格式 第一行包含整数 n。 接下来 n 行&#xff0c;每行包含 n1…

千万不要支付赎金!解密.halo勒索病毒的秘诀在这里

导言&#xff1a; .halo 勒索病毒等勒索病毒已经成为网络犯罪分子的利器&#xff0c;威胁着很多企业的数据安全。本文91数据恢复将为您介绍 .halo 勒索病毒的新面貌&#xff0c;以及一些创新的方法&#xff0c;如何保护和恢复被 .halo 勒索病毒加密的数据文件&#xff0c;并提供…

【计算机视觉|人脸建模】学习从图像中回归3D面部形状和表情而无需3D监督

本系列博文为深度学习/计算机视觉论文笔记&#xff0c;转载请注明出处 标题&#xff1a;Learning to Regress 3D Face Shape and Expression from an Image without 3D Supervision 链接&#xff1a;[1905.06817] Learning to Regress 3D Face Shape and Expression from an I…

6-10 单链表分段逆转 分数 15

void K_Reverse( List L, int K ) { //此题已经默认size > K 因为当size < K时 反转后将不再符合链表的定义//求出表中元素个数int size 0;for (List cur L->Next; cur ! NULL; cur cur->Next)size; List prv, cur, next, first, head L;//共需要反转 si…

功率放大器可以放大电压吗为什么

功率放大器是一种电子设备&#xff0c;用于将输入信号的功率放大到更高的水平。而电压是功率的一个组成部分&#xff0c;所以功率放大器可以放大电压。 在功率放大器中&#xff0c;输入信号经过放大器的放大阶段后&#xff0c;会得到一个更强的输出信号。这个放大过程是通过增加…

HTML5开发实例-3D全景(ThreeJs全景Demo) 详解(图)

前言 在现在市面上很多全景H5的环境下,要实现全景的方式有很多,可以用css3直接构建也可以用基于threeJs的库来实现,还有很多别的制作全景的软件使用 本教学适用于未开发过3D全景的工程狮 如果觉得内容太无聊可以直接跳到最后 下载代码 理论 整个3D全景所用的相关理论就…

CSS布局 | flex布局

flex布局 flex是CSS3中新增的布局手段&#xff0c;优势是适用于不同屏幕尺寸和设备&#xff0c;当布局涉及到不定宽度&#xff0c;分布对⻬的场景时&#xff0c;我们可以优先考虑弹性盒布局。 任何一个容器都可以指定为Flex布局&#xff0c;容器设为 Flex 布局以后&#xff0…

电驱2035目标及新材料研究应用进展-2023

今天同大家一起了解DOE电驱2035目标&#xff08;成本、功率密度、电压、峰值功率&#xff09;&#xff0c;及当前研发项目中关于电驱电机的新材料研究进展与应用。 2030-2035电驱系统目标 峰值功率和功率密度按每5年50%的速度提升&#xff0c;电压平台800V&#xff0c;增加峰值…

数据被加密?.locked1勒索病毒的简单解决方法

引言&#xff1a; 在数字化的今天&#xff0c;数据宛如生命的一部分&#xff0c;而 .locked1 勒索病毒这种威胁正在如影随形地威胁着我们的数字宝库。本文将为您生动地介绍 .locked1 勒索病毒&#xff0c;以及如何摆脱它的束缚&#xff0c;解锁被其加密的数据&#xff0c;同时提…

Unity Golang项目教程-创建项目

安装Unity Unity的安装比较简单。这里我不做详细介绍&#xff0c;提供一些安装教程链接&#xff0c;如果还有困难下面我提供联系方式可以私信我。 安装教程参考 创建工程如下图所示&#xff1a; 等待项目创建完成即可。 如有问题可以Q联系我&#xff0c; 873149745

CCF中国开源大会专访 | 刘旭东:着眼“开源联合”,实现“聚力共赢”

受访嘉宾 | 刘旭东 记者 | 朱珂欣 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 2023 CCF 中国开源大会&#xff08; CCF ChinaOSC &#xff09;拟于 2023 年 10 月 21 日至 22 日在湖南省长沙市北辰国际会议中心召开。 作为第二届 CCF 中国开源大会&a…

计算CPK及规范限合格率,并绘制概率密度曲线

CPK&#xff08;过程能力指数&#xff09;是一个用于衡量一个过程的稳定性和一致性的统计指标&#xff0c;特别用于制造业和质量管理中。它衡量了一个过程的变异性与规范界限的关系&#xff0c;帮助确定过程是否能够产生合格的产品或服务。 正态分布假设&#xff1a;CPK的计算…

Kfka监控工具--Kafka-eagle安装

1、开启Kafka JMX端口 JMX 是一个为应用程序植入管理功能的框架 在启动Kafka脚本之前&#xff0c;添加&#xff1a; export JMX_PORT9988 nohup bin/kafka-server-start.sh comfig/server.properties 2、安装jdk配置好JAVA_HOME 3、将kafka_eagle 上传并解压 tar -zxvf …

想做扫码看图效果,你需要学会这一招

现在扫描二维码来查看图片是常见的一种方式&#xff0c;比如资料图片、个人照片、pdf图片、表情包等等都可以通过扫码的方式来展现。而且生成图片二维码的方法也非常的简单&#xff0c;只需要使用二维码在线生成器&#xff0c;就可以使用浏览器来快速完成制作&#xff0c;对于还…

VS2022+qt5.15.2+cmake3.23.2配置VTK9.1.0版本

VS2022qt5.15.2cmake3.23.2VTK9.1.0 尝试了好多次&#xff0c;终于成了~ 软件安装 先把需要的软件都安装好&#xff01; VS2022安装教程: https://blog.csdn.net/qq_44005305/article/details/132295064 qt5.15.2安装教程&#xff1a;https://blog.csdn.net/Qi_1337/article…

python—如何提取word中指定内容

假设有一个Word&#xff0c;该Word中存在 “联系人” 关键字&#xff0c;如何将该Word中的联系人所对应的内容提取出来呢&#xff1f; 该Word内容如下所示&#xff1a; 要在给定的Word文档中提取出与"联系人"关键字对应的内容&#xff0c;可以使用Python的py…

qt开发从入门到实战2

以下是本人学习笔记 原视频&#xff1a;最新QT从入门到实战完整版|传智教育 qt开发从入门到实战1 练习示例 设计一个按钮&#xff0c;点击时弹出新窗口&#xff0c;再次点击时新窗口关闭 // exerciseQWidget* second_window new QWidget();QPushButton* btn3 new QPushBu…