DAY55:单调栈(一)每日温度+下一个更大元素Ⅰ

news2024/11/17 13:17:54

文章目录

    • 739.每日温度
      • 栈数据结构
      • 单调栈思路
      • 单调栈原理
        • 单调栈注意点
        • 判断条件
        • 工作过程分析
      • 完整版
    • 496.下一个更大元素Ⅰ
      • 思路
        • 映射思路
      • 完整版
      • 总结

739.每日温度

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。

示例 1:

输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]

示例 2:

输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]

示例 3:

输入: temperatures = [30,60,90]
输出: [1,1,0]

提示:

  • 1 <= temperatures.length <= 10^5
  • 30 <= temperatures[i] <= 100

栈数据结构

首先复习一下栈,栈是一种容器适配器,并不属于容器。

std::stack - cppreference.com

STL 容器简介 - OI Wiki (oi-wiki.org)

DAY9:栈和队列(一):栈和队列基础_大磕学家ZYX的博客-CSDN博客

在这里插入图片描述
栈基本上能够使用的成员函数只有访问栈顶,插入栈顶元素和弹出栈顶元素。

在这里插入图片描述

单调栈思路

单调栈就适用于找某个元素左面或者右面,第一个比它大或者比它小的元素

也就是说,一维数组内,要寻找任一元素的右侧或左侧,第一个比自身大或者小的元素位置,此时我们就要想到用单调栈。单调栈时间复杂度为O(n)。寻找的方向,第一个元素是大还是小,都是同一个原理。

单调栈原理

那么单调栈的原理是什么?为什么时间复杂度是O(n),就可以找到每一个元素的右边第一个比它大的元素位置呢?

单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是整个数组只需要遍历一次。

更直白来说,就是用一个栈来记录我们遍历过的元素。因为我们遍历数组的时候,我们不知道之前都遍历了哪些元素,以至于遍历一个元素找不到是不是之前遍历过一个更小的,所以我们需要用一个容器(这里用单调栈)来记录我们遍历过的元素。

单调栈注意点

在使用单调栈的时候首先要明确如下几点:

  • 单调栈里存放的元素是什么?

单调栈里只需要存放遍历过的元素的下标i就可以了,如果需要使用对应的元素,直接T[i]就可以获取

在进行新元素与栈顶元素的比较时,其实是T[i]T[st.top()]的比较!st内部存放的是元素下标

  • 单调栈里元素是递增还是递减

注意单调栈中,顺序的描述为从栈头到栈底的顺序,如果是单调递增栈,那么栈顶部是栈内最小元素

本题中,我们要找到的是元素右侧第一个比它大的元素,因此我们需要使用单调递增栈。因为只有递增的时候,栈里要加入一个元素i时,才知道栈顶元素在数组中右面第一个比栈顶元素大的元素是i

即:如果求一个元素右边第一个更大元素,单调栈就是递增的;如果求一个元素右边第一个更小元素,单调栈就是递减的。

判断条件

使用单调栈主要有三个判断条件。

  • 当前遍历的元素T[i] < 栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i] = 栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i] > 栈顶元素T[st.top()]的情况

工作过程分析

用temperatures = [73, 74, 75, 71, 71, 72, 76, 73]为例,分析单调递增栈的工作过程。

输出应该为[1,1,4,2,1,1,0,0]。

在这里插入图片描述
由此可见,当我们找到一个比栈顶元素大的元素时,栈顶元素就会弹出,并且如果下一个栈顶元素还是比当前元素小,会继续弹出,直到当前元素比栈内元素都小,才会加入递增栈中。

这种方法能够找到右侧第一个最大元素,就是因为递增栈的特性,栈内递增所以被弹出的时候,就是找到了第一个比当前元素大的元素

完整版

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        //建立递增栈
        stack<int>st;
        st.push(0);//注意栈是存放下标
        vector<int>result(temperatures.size(),0);
        
        for(int i=1;i<temperatures.size();i++){
            //三种情况
            if(temperatures[i]<=temperatures[st.top()]){
                st.push(i);
            }
            else{//大于
                while(!st.empty()&&temperatures[i]>temperatures[st.top()]){
                    result[st.top()]=i-st.top();
                    st.pop();
                }
                st.push(i);//while结束之后把新元素放进栈里
            }
        }
        return result;      
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

496.下一个更大元素Ⅰ

nums1 中数字 x下一个更大元素 是指 xnums2 中对应位置 右侧第一个x 大的元素。

给你两个 没有重复元素 的数组 nums1nums2 ,下标从 0 开始计数,其中nums1nums2 的子集。

对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j]下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1

返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素

示例 1:

输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
- 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
- 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。

示例 2:

输入:nums1 = [2,4], nums2 = [1,2,3,4].
输出:[3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。
- 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。

提示:

  • 1 <= nums1.length <= nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 10^4
  • nums1nums2中所有整数 互不相同
  • nums1 中的所有整数同样出现在 nums2

**进阶:**你可以设计一个时间复杂度为 O(nums1.length + nums2.length) 的解决方案吗?

思路

本题和上一题基本相同,区别在于多了两个数组的映射。题目要求,nums1 中数字 x下一个更大元素 是指 xnums2 中对应位置 右侧第一个x 大的元素。

因此我们可以先求nums2中所有元素对应的下一个更大元素,再在结果中,将nums1中的元素值nums2的key值做映射,nums1中元素值对应的结果,就是nums2的key值对应的value

映射思路

我们可以利用哈希表nums2的元素值该元素值下一个最大元素关联起来。元素值为key,对应的下一个最大元素为value(因为哈希表查找只能查找key)。

实际上,我们也可以用数组关联nums2的元素值与其下一个最大元素,元素值为下标i,对应下一个最大元素为result[i]。但是,数组内存分布是连续的,如果Nums2里面出现了较大的元素,那么会导致数组下标要开的很大,会浪费大量内存空间。题目中nums2[i]的取值是10^4,说明会有较大的数据,导致数组内存浪费。

如果我们已知元素值的范围并且范围比较小,那么使用数组作为映射可能更优,因为数组提供了更快的访问速度,而且可能更容易实现。但是,如果元素值可能很大,那么数组就不是一个好的选择,因为会浪费大量的内存空间。大多数情况下,如果键和值之间的关系是任意的,那么哈希表通常是更好的选择

加上题目说了数组内没有重复元素,因此可以用unordered_map(key不可重复)来实现。

完整版

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        stack<int>st;
        vector<int>result(nums1.size(),-1);
        unordered_map<int,int>umap;//哈希表作为nums2的元素值-结果值映射存储
        st.push(0);
        for(int i=1;i<nums2.size();i++){
            if(nums2[i]<=nums2[st.top()]){
                st.push(i);
            }
            else{
                while(!st.empty()&&nums2[i]>nums2[st.top()]){
                    umap[nums2[st.top()]]=nums2[i];//键值对存放元素值-下一个最大元素
                    st.pop();
                }
                st.push(i);
            }
        }     
        //遍历第一个数组,找元素值相同的,取其键值作为结果
        for(int i=0;i<nums1.size();i++){
            if(umap.find(nums1[i])!=umap.end()){
                result[i]=umap[nums1[i]];
            }
        }
		return result;
    }
};
  • 时间复杂度: O(nums1.length + nums2.length)

  • 空间复杂度: O(nums2.length)

    • 我们使用了一个栈存储 nums2 中的元素,所以空间复杂度是 O(nums2.length)。
    • 我们使用了一个哈希表存储 nums2 中元素的值其下一个更大元素的值的映射,由于 nums2 中的元素都是唯一的,所以最多会有 nums2.length 个映射,所以空间复杂度也是 O(nums2.length)。

    所以总的空间复杂度是 O(nums2.length)。

总结

本题只要想明白映射关系,因为nums1元素需要和nums2元素进行对应,对应的结果是nums2元素的下一个最大元素。因此我们可以先把nums2元素的元素值-下一个最大元素进行键值对的对应,再遍历nums1,查找Key值相同的时候,对应的结果值。

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

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

相关文章

2023年第四届“华数杯”数学建模思路 - 案例:异常检测

文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常检测 异常…

【Java】UWB高精度工业人员安全定位系统源码

基于VueSpring boot前后端分离架构开发的一套UWB技术高精度定位系统源码。 UWB高精度人员定位系统提供实时定位、电子围栏、轨迹回放等基础功能以及各种拓展功能,用户可根据实际需要任意选择搭配拓展功能。该系统简易部署&#xff0c;方便使用&#xff0c;实时响应。UWB高精度定…

Java on Azure Tooling 6月更新|标准消费和专用计划及本地存储账户(Azurite)支持

作者&#xff1a;Jialuo Gan - Program Manager, Developer Division at Microsoft 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎阅读 Java on Azure 工具的六月更新。在本次更新中&#xff0c;我们将介绍 Azure Spring Apps 标准消费和专用计划支持以及本地存储账户&…

二叉树迭代遍历

PS:以下代码均为C实现 1.二叉树前序遍历 力扣 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 class Solution { public:vector<int> preorderTraversal(TreeNode* root) {stack<TreeNode*> st;vector<int> str;TreeNode* curroot;whil…

【波浪动态特效】基于jquery实现页面底部波浪动画效果(附完整源码下载)

文章目录 写在前面涉及知识点实现效果1、搭建页面1.1、创建两个片区1.2、创建波浪区域1.3、静态页面源码 2、JS实现波浪效果2.1 动画原理2.2 动画源码 3、源码分享3.1 百度网盘3.2 123云盘3.3 邮箱留言 总结 写在前面 想必搭建过企业官网的大多数对这个效果不陌生吧&#xff0…

备战秋招 | 笔试强训21

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、设一个有序的单链表中有n个结点&#xff0c;现要求插入一个新结点后使得单链表仍然保持有序&#xff0c;则该操作的时间复杂度&#xff08;&#xff09; A. O(log2n) B. O(1) C. O(n2) D. O(n) 2…

网络中通过IP地址查找位置

display ip routing-table 查看路由表 display vlan 查看vlan 信息 display stp brief 查看生成树信息 display mac-address 查看mac 地址表 display arp 查看arp表 SW1 SW2

海量小文件传输慢的原因以及对应的优化方案

在日常工作中&#xff0c;我们经常遇到需要传输一些小文件的情况&#xff0c;但是当小文件的数量很多的时候&#xff0c;为什么小文件传输的速度就会变得很慢呢&#xff1f;为什么复制许多较小的文件时&#xff0c;小文件传输效率就会降低呢&#xff1f;针对这些问题&#xff0…

MyBatis查询数据库(3)

前言&#x1f36d; ❤️❤️❤️SSM专栏更新中&#xff0c;各位大佬觉得写得不错&#xff0c;支持一下&#xff0c;感谢了&#xff01;❤️❤️❤️ Spring Spring MVC MyBatis_冷兮雪的博客-CSDN博客 前面我们讲解了MyBatis增删改查基本操作&#xff0c;下面我们来深入了解M…

谷歌语音助手战略调整:开发 AI 新版,调整裁员计划

北京时间8月2日晚间&#xff0c;谷歌通过对 “谷歌助手” 团队进行调整和裁员&#xff0c;意图改变其开发方向。经过此次变动&#xff0c;谷歌计划借助最新的生成式人工智能技术和大型语言模型来提升 谷歌助手 的能力。此次调整表明语音助手市场未达到先前的预期。 亚马逊旗下的…

PT Industrial Security Incident Manager 扩展了对 Emerson 和 GE Fanuc 控制器的支持

&#x1f504; 我们发布了 PT Industrial Security Incident Manager (PT ISIM) 深度流程流量分析系统的下一套专业知识。 有哪些新功能&#xff1f; 1. 改进了 GE Fanuc (Emerson) GE-SRTP 协议的操作。该协议专为 GE Fanuc 控制器与工程软件&#xff08;Proficy Machine E…

ArmSoM-W3之RK3588安装Qt+opencv+采集摄像头画面

1. 简介 场景&#xff1a;在RK3588上做qt开发工作 RK3588安装Qtopencv采集摄像头画面 2. 环境介绍 这里使用了OpenCV所带的库函数捕获摄像头的视频图像。 硬件环境&#xff1a; ArmSoM-RK3588开发板、&#xff08;MIPI-DSI&#xff09;摄像头 软件版本&#xff1a; OS&…

angular框架——node_modules引入ng-zorro-antd问题

发生错误 在安装npm包&#xff08;ng-zorro-antd&#xff09;的时候&#xff0c;报错如下 原因 项目依赖的ng-zorro-antd版本号和引用包的17.0.2版本号不一致&#xff0c;项目使用的16.13.1版本号太高了&#xff0c;无法解析依赖树中低版本。 解决方案 &#xff1a; 命令修…

pointpillars的demo过程记录

1、进入pp conda activate pp 2、cd到/home/fyy/OpenPCDet-master/tools打开终端 python demo.py --cfg_file cfgs/kitti_models/pointpillar.yaml --ckpt /home/fyy/OpenPCDet-master/pointpillar_7728\ \(1\).pth --data 000009.bin 直接就可以demo显示了

数据库同步时,通过存储过程找出时间内发生变化的视图和物化视图

1. 应用场景 在软件开发或数据库运维过程&#xff0c;每一次数据库同步都是运维人员的痛苦的过程。 如果每次都是无脑全量更新&#xff0c;则工作量较大如果每次都是增量更新&#xff0c;则需要知道哪些视图谁在什么时候修改了&#xff0c;增加了什么信息&#xff08;因为往往…

(学习笔记-内存管理)内存满了会发生什么?

内存分配过程 应用程序通过 malloc 函数申请内存的时候&#xff0c;实际上申请的是虚拟内存&#xff0c;此时并不会分配物理内存。 当应用程序读写了这块虚拟内存&#xff0c;CPU就会去访问这个虚拟内存&#xff0c;这时会发现这个虚拟内存没有映射到物理内存&#xff0c;CPU…

【WiFi】国产WiFi芯片

目录 1.概述 2.WiFi芯片的市场格局 3.中国的WiFi芯片公司 3.1.华为海思 3.2.乐鑫科技 3.3.博通集成 3.4.紫光展锐 3.5.康希通信 3.6.南方硅谷 4.国产WiFi芯片竞争格局 4.1.内卷WiFi 4 4.2.缺席WiFi 5 4.3.发力WiFi 6 4.4.逐鹿WiFi 7 5.不得不提的WiFi FEM 1.概述…

视频创作者福音,蝰蛇峡谷NUC12SNKI7视频剪辑测评

英特尔NUC绝对是PC市场里最为特殊的产品&#xff0c;相比众多OEM设计制造的台式机而言&#xff0c;英特尔NUC主打小体积、高度集成化、强扩展性以及尽可能优异的性能表现。尤其是在主打游戏体验的NUC产品出现之后&#xff0c;更是将极致体验演绎到了极致。 在搭载独显的幻影峡谷…

Python爬虫教程篇+图形化整理数据(数学建模可用)

一、首先我们先看要求 1.写一个爬虫程序 2、爬取目标网站数据&#xff0c;关键项不能少于5项。 3、存储数据到数据库&#xff0c;可以进行增删改查操作。 4、扩展&#xff1a;将库中数据进行可视化展示。 二、操作步骤&#xff1a; 首先我们根据要求找到一个适合自己的网…

gitlab CI/CD 安装 gitlab runner

一、为什么需要安装gitlab runner &#xff1f; 极狐GitLab Runner 极狐GitLab Runner 是在流水线中运行作业的应用&#xff0c;与极狐GitLab CI/CD 配合运作。 说白了就是你部署的一个agent。 二、如何安装&#xff1f; 1.介绍通过helm部署github runner 2.helm添加仓库 h…