Day58【单调栈】739.每日温度、496.下一个更大元素 I

news2024/11/24 8:53:37

739.每日温度

力扣题目链接/文章讲解

视频讲解

暴力解法很容易想到。外层 for 遍历填充 answer,内层 for 针对每一天去寻找下一个更高温度 

直接超时 

本题可以采用单调栈解决! 

什么是单调栈?

从名字上就听的出来,单调栈中存放的数据应该是有序的

维护单调栈的关键就是维护这个有序性,假设我们需要维护一个从栈顶到栈底单调递增的栈

在入栈元素时,如果栈为空入栈元素值小于栈顶元素值,则入栈

否则,如果直接入栈则会破坏栈的单调性,则需要先把比入栈元素小的栈顶元素全部出栈后,再入栈

本题怎么利用单调栈解决?本质上是利用一个栈来记录我们遍历过的元素

本题大致过程是单调栈中存放元素下标,按照元素值从栈顶到栈底递增存放,元素出栈时记录一次结果

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        
        stack<int> st;  
        // 递增栈,注意栈中存的是temperatures的下标,但“递增”形容的是temperatures的值
        // 递增栈指从栈顶到栈底元素递增

        vector<int> answer(temperatures.size(), 0);    // 存放结果,题目要求默认为0

        st.push(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()])    // 注意栈非空
                {
                    answer[st.top()] = i - st.top();    // 出栈时记录一次结果
                    st.pop();
                }
                st.push(i);    // 然后再入栈
            }
        }

        return answer;        
    }
};

详细过程可以见视频讲解,感觉已经很清晰了 

496.下一个更大元素 I 

力扣题目链接/文章讲解 

视频讲解 

一维数组中,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素,此时我们又可以想到用单调栈 

需要用一个栈来记录遍历过的元素,本题我们要在 nums2 中找下一个更大元素,因此遍历 nums2,并用单调递增栈记录

在入栈元素时,如果栈为空入栈元素值小于栈顶元素值,则入栈

否则,如果直接入栈则会破坏栈的单调性,则需要先把比入栈元素小的栈顶元素全部出栈后,再入栈

本题大致过程是单调栈中存放元素,按照元素值从栈顶到栈底递增存放,元素出栈时记录结果

stack<int> st;    // 从栈顶到栈底元素单调递增的栈
st.push(nums2[0]);
for (int i = 1; i < nums2.size(); ++i) {    // 遍历nums2
    if (nums2[i] <= st.top())    // 入栈元素小于等于栈顶元素,直接入栈不会破坏单调性
        st.push(nums2[i]);
    else {
        while (!st.empty() && nums2[i] > st.top()) {    // 将比入栈元素小的元素全部出栈后
            
            // 元素出栈时做记录    
            
            st.pop();
        }
        st.push(nums2[i]);    // 再入栈
    }
}

此时我们看看怎么记录结果

根据题目要求,当出栈元素是 nums1 中的元素时,才记录在 nums1 中元素对应下标的位置

为了实现这种需求,我们先搭建一个 nums1 中元素到元素下标的映射

unordered_map<int, int> umap;   // k:nums1中元素 v:元素对应下标
for (int i = 0; i < nums1.size(); ++i)
    umap[nums1[i]] = i;

然后在记录结果的时候看看出栈元素是否为 nums1 中的元素即可

if (umap.count(st.top()) > 0)    // 刚才映射中有记录,说明出栈元素是nums1中的元素
{
    ans[umap[st.top()]] = nums2[i];
    // umap[st.top()]获取出栈元素在nums1中的下标位置,需要将结果记录在ans的该位置
    // nums2[i]就是出栈元素右侧的第一个比其大的元素  
}

整体代码如下 

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        
        vector<int> ans(nums1.size(), -1);

        unordered_map<int, int> umap;   // k:nums1中元素 v:元素对应下标
        for (int i = 0; i < nums1.size(); ++i)
            umap[nums1[i]] = i;

        stack<int> st;    // 从栈顶到栈底元素单调递增的栈
        st.push(nums2[0]);
        for (int i = 1; i < nums2.size(); ++i) {    // 遍历nums2
            if (nums2[i] <= st.top())    // 入栈元素小于等于栈顶元素,直接入栈不会破坏单调性
                st.push(nums2[i]);
            else {
                while (!st.empty() && nums2[i] > st.top()) {    // 先不断将比入栈元素小的元素全部出栈后
            
                    // 元素出栈时做记录   
                    if (umap.count(st.top()) > 0)    // 刚才映射中有记录,说明出栈元素是nums1中的元素
                    {
                        ans[umap[st.top()]] = nums2[i];
                        // umap[st.top()]获取出栈元素在nums1中下标位置,需要将结果记录在ans的该位置
                        // nums2[i]就是出栈元素右侧的第一个比其大的元素  
                    }
            
                    st.pop();
                }
                st.push(nums2[i]);    // 再入栈
            }
        }

        return ans;

    }
};

回顾总结 

单调栈的关键就是维护栈中元素的单调性 

关键就是入栈时候不能破坏栈中元素的单调性 

单调栈适合解决的问题:一维数组中,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素

单调栈解决问题的过程需要多看视频和动图解析,还是很容易理解的 

另外简单说一下确定递增递减栈的思路过程:(从栈顶到栈底递增还是递减)

找下一个更大,说明需要记录下一个更大,即遇到更大的入栈才需要出栈并记录,说明遇到更大的入栈会破坏单调性,因此是递增栈

找下一个更小,说明需要记录下一个更小,即遇到更小的入栈才需要出栈并记录,说明遇到更小的入栈会破坏单调性,因此是递减栈

 

 

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

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

相关文章

创建型设计模式05-抽象工厂模式

✨作者&#xff1a;猫十二懿 ❤️‍&#x1f525;账号&#xff1a;CSDN 、掘金 、个人博客 、Github &#x1f389;公众号&#xff1a;猫十二懿 抽象工厂模式 1、抽象工厂模式介绍 抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是一种创建型设计模式&#x…

MATLAB按照曲线模型拟合数据

用到了曲线拟合工具箱&#xff0c;如果没有下载需要另外安装&#xff1a; 没有下载的话在命令行内输入cftool不会弹出窗口&#xff0c;而是提示没有这个命令 在菜单栏的APP&#xff1a; 点击获取更多APP&#xff1a; 在弹出的窗口输入Curve Fitting Toolbox 注意这里输入cft…

100种思维模型之多维视角思维模型-70

“多维视角思维模型”让我们用众生之眼看世界&#xff0c;继而看见更真实世界的思维模型。 01、何谓多维度视角思维模型 一、多维度视角 所谓多维视角&#xff0c;指的是除了用自己本能的视角看待问题&#xff0c;还会用360度其他人的视角&#xff0c;如对立面的视角&#xff…

仅用自然语言,让ChatGPT输出连贯的长篇小说!苏黎世联邦理工大学提出RecurrentGPT

夕小瑶科技说 原创 作者 | ZenMoore&#xff0c;Wangchunshu Zhou 前言 ChatGPT 是万能的吗&#xff1f; 显然不是&#xff0c;至少在今天我们所讨论的长文本生成上&#xff0c;ChatGPT 可以说是几乎完全不太可能生成长篇小说。 在某种程度上&#xff0c;这是 Transformer 模…

2自由度并联关节的制作

1. 运动功能说明 2自由度并联关节模组的主要运动方式为用舵机带动连杆摆动。 2. 结构说明 构成本模组的零部件主要是舵机&#xff08;行程0度~180度&#xff09;、舵机支架、舵机输出头、连杆、螺丝、螺母等。此模组的机械系统介绍及运动学算法讲解可参考【R306】5自由度并联机…

回收站不见了怎么恢复?3个方法快速解决!

案例&#xff1a;我想把需要删除的软件拖到桌面回收站中进行删除&#xff0c;却发现我电脑桌面上的回收站不见了&#xff0c;有小伙伴知道怎么恢复吗&#xff1f; 在日常使用电脑的过程中&#xff0c;回收站是一个至关重要的功能。当我们删除文件时&#xff0c;它提供了一个安…

git 远端分支管理、仓库迁移:017

1. 在Github上创建分支&#xff1a; 2. 在Github上删除分支&#xff1a; 3. 使用命令来删除远端分支&#xff1a; 如果远端分支发生改变&#xff0c; 需要通过git pull来获取远端最新分支&#xff0c;如下图&#xff0c;就可以看到获取到了最新分支&#xff1a; 查看本地分支和…

springboot+vue新闻稿件java在线投稿管理系统

本文介绍了新闻稿件管理系统的开发全过程。通过分析新闻稿件管理系统管理的不足&#xff0c;创建了一个计算机管理新闻稿件管理系统的方案。文章介绍了新闻稿件管理系统的系统分析部分&#xff0c;包括可行性分析等&#xff0c;系统设计部分主要介绍了系统功能设计和数据库设计…

数据库整理

文章目录 1、将Excel转换为CSV1.1 代码 2、将CSV文件的数据追加到另一个CSV文件2.1 代码 3 、另外的发现 背景&#xff1a;在数据库里面导出来一批excel文件&#xff0c;现在需要将这些数据进行合并为csv文件 分两步&#xff1a; 1、将Excel转换为CSV 参考&#xff1a;用Pytho…

如何使用宝塔面板搭建网站(搭建宝塔页面)

书接上回&#xff0c;咱们已经搭建好咱们的Linux服务器&#xff0c;接下来改是搭建宝塔页面的教程了。 这里我们需要一个域名&#xff0c;自行去各家云服务器购买域名&#xff08;例如&#xff1a;腾讯云&#xff0c;阿里云&#xff0c;华为云等等&#xff09; 购买一个域名之…

FPGA纯vhdl实现XGMII接口10G万兆网UDP协议DMA传输 配合10G Ethernet PCS/PMA使用 提供工程源码和技术支持

目录 1、前言2、我这里已有的UDP方案3、详细设计方案传统UDP网络通信方案本方案详细设计说明DMA和BRAMAXIS-FIFO10G-UDP协议栈10G Ethernet PCS/PMA IP核输出 4、vivado工程详解Block Design设计SDK设计 5、上板调试验证并演示6、福利&#xff1a;工程代码的获取 1、前言 目前…

【ChatGPT】开发人员教程:38 种提高 10 倍工作效率的方法(附Youtube视频地址)...

1. 推荐3本顶级的学习xx的书籍 2. 询问细节&#xff1a;“Head first Java”的主要内容是什么&#xff1f;What are the key takeaways from "Head first Java"? 3. 我如何成为一名前端开发人员&#xff1f;How do I become a front-end developer? &#xff08;英…

JVM-常用工具(jps、jstat、jinfo、jmap、jhat、jstack、jconsole、jvisualvm)使用

场景 记录JVM中常用工具。 jps:虚拟机进程状态工具 jps(JVM Process Status Tool)&#xff1a;虚拟机进程状态工具&#xff0c;可以列出正在运行的虚拟机进程&#xff0c; 并显示虚拟机执行主类&#xff08;Main Class&#xff0c;main()函数所在的类&#xff09;的名称&am…

【Mininet】安装篇:安装Mininet

大家好&#xff0c;我是皮皮猫吖&#xff01; 每文一言&#xff1a;改变你的生活&#xff0c;现在或者从不 本篇文章&#xff1a; 本文是安装 mininet 的简单过程。 正文如下&#xff1a; 一、Mininet的安装 第一步&#xff1a;安装git apt install git 第二步&#xff…

element-ui配置按需引入和全局引入

镇楼图 按需引入 安装element-plus cnpm install element-plus --save 安装按需导入 cnpm install -D unplugin-vue-components unplugin-auto-import修改vite.config.js配置按需加载 import AutoImport from unplugin-auto-import/viteimport Components from unplugin-vue-…

30天从入门到精通TensorFlow1.x第一天,如何创建张量

文章目录 一、TensorFlow基本概念1. 什么是TensorFlow2. TensorFlow的组成3. TensorFlow的三个重要模型 二、TensorFlow的重要底层库1. 先简单来个 helloWord2. 张量什么是张量如何创建张量创建张量&#xff08;1&#xff09;. 通过定义常量来进行创建张量&#xff08;2&#x…

Java学习笔记21——常用API

常用API 常用APIMath类Math的常用方法 System类System类常用方法 Object类Object类常用方法 Arrays类Arrays常用方法 基本类型包装类Integer类的概述和使用int和String的相互转换自动装箱和拆箱 日期类Date类Date类的常用方法 SimpleDateFormat类SimpleDateFormat的构造方法Sim…

【计算机网络实验】静态路由协议和RIP协议仿真实验

实验内容  静态路由协议和RIP协议仿真实验 实验目的 1 路由器及路由协议基础知识 2 静态路由配置实验 &#xff08;1&#xff09;掌握静态路由和RIP的配置方法&#xff1b; &#xff08;2&#xff09;掌握通过静态路由和RIP方式实现网络的连通性&#xff1b; &#xff08;3…

什么是品牌推广?品牌推广的基本概念及注意要点

品牌推广是企业进行营销活动的关键之一&#xff0c;而现代市场竞争激烈&#xff0c;如何进行有效的品牌推广也成为企业最为关心的问题之一。本文将为大家介绍品牌推广的基本概念、策略以及注意事项。 一、品牌推广的基本概念 品牌推广是指企业通过多种手段&#xff0c;以宣传产…

电脑软件:键盘按键修改器——keytweak使用介绍

对你的电脑键盘的布局不满意、键盘上的某个按键坏掉了等等键盘问题如何解决&#xff1f;有了KeyTweak这一切就可以轻松解决了&#xff0c;KeyTweak是一个免费软件程序&#xff0c;使用它可让你重新映射键盘键。如果您改变主意并想将其改回原样&#xff0c;只需点击一下即可容易…