Day49 力扣单调栈 : 739. 每日温度 |496.下一个更大元素 I
Day49 力扣单调栈 : 739. 每日温度 |496.下一个更大元素 I
- 739. 每日温度
- 第一印象
- 看完题解的思路
- 什么是单调栈?
- 我的总结
- 实现中的苦难
- 感悟
- 代码
- 496.下一个更大元素 I
- 第一印象
- 看完题解的思路
- 实现中的困难
- 感悟
- 代码
739. 每日温度
今天正式开始单调栈,这是单调栈一篇扫盲题目,也是经典题。
大家可以读题,思考暴力的解法,然后在看单调栈的解法。 就能感受出单调栈的巧妙
https://programmercarl.com/0739.%E6%AF%8F%E6%97%A5%E6%B8%A9%E5%BA%A6.html
第一印象
暴力解法还是比较好想的
class Solution {public int[] dailyTemperatures(int[] temperatures) {int[] answer = new int[temperatures.length];for (int i = 0; i < answer.length; i++) {int curTemp = temperatures[i];int day = 1;//flag 0代表没有更高的那天,1代表有更高的那天int flag = 0;for (int j = i + 1; j < temperatures.length; j++) {if (temperatures[j] > curTemp) {answer[i] = day;flag = 1;break;} else {day++;}}if (flag == 0) answer[i] = 0;}return answer;}
}
当然,直接超时了,下面学习单调栈。
看完题解的思路
我看完单调栈的工作过程了, 太tm神奇了.
什么是单调栈?
单调栈就是用于找一个元素左 / 右第一个比自己大 / 小的元素的题目。
单调栈的本质是空间换时间, 更直白来说,就是用一个栈来记录我们遍历过的元素,因为我们遍历数组的时候,我们不知道之前都遍历了哪些元素,以至于遍历一个元素找不到是不是之前遍历过一个更小的,所以我们需要用一个容器(这里用单调栈)来记录我们遍历过的元素。
在使用单调栈的时候首先要明确如下几点:
1.单调栈里存放的元素是什么?
单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接T[i]就可以获取。
2.单调栈里元素是递增呢? 还是递减呢?
注意以下讲解中,顺序的描述为 从栈头到栈底的顺序,因为单纯的说从左到右或者从前到后,不说栈头朝哪个方向的话,大家一定比较懵。
这道题我们要让栈里的元素是递增的 (从栈头到栈底)
对于数组我们从左到右遍历, 每次拿来的元素 i 都是遍历过的元素的右面的. 这就实现了找右面更大 / 更小的元素.
而栈里, 我们让元素都是递增的. 这样每次拿来元素 i ,就是 栈顶元素右侧第一个比栈顶元素大的. 这里会产生一个疑问: 比如栈里是 69 71. 71 不是比栈顶元素 69 大吗?
是的, 但 71 是 69 左侧的元素. 因为数组遍历顺序是从左到右, 然后压入栈. 所以越靠近栈头的元素在数组里越靠右, 栈尾则靠左.
那如果拿来的元素 i 比栈顶元素更小呢? 那压入栈就可以了. 栈递增所以栈顶元素就是栈里最小的, 拿到的元素 i 比最小的还要小, 所以不会比栈内任何元素大, 就说明还没找到这些元素右侧第一个更大的.
我的总结
所以求右侧第一个更大元素时, 为什么让栈内元素递增?
因为栈内元素递增, 栈头元素就是最小的那个. 因为数组从左到右遍历, 栈头元素是右侧的, 栈底元素是左侧的.
每次拿来元素 i 和栈头元素比较, 没有栈头大就没有任何栈内元素大, 就压入栈.
元素 i 比栈头元素大, 就找到了栈头元素右侧第一个更大. 记录结果, 弹出栈头元素. 当然也要用元素 i 继续和新栈头元素比较, 直到元素 i 比新栈头元素小而压入栈, 或者栈空了元素 i 就压入栈.
那么如果找右侧第一个更小, 就应该让栈内元素递减了.
每次其实只有三种操作:
- 元素 i 比栈头元素大
- 元素 i 比栈头元素小
- 元素 i 和栈头元素相等
只要分别写出三中操作的代码, 就写完这道题了. 用这三种操作控制栈内元素是递增的, 就可以了.
实现中的苦难
思路清晰没有困难
int index = stack.pop();
answer[index] = i - index;
记录结果的时候要注意别岔劈了.
感悟
具体的图解模拟过程, 到代码随想录里看一下吧.
第一次看完视频感觉单调栈很神奇, 甚至有点不知道为什么会产生这种效果.
我觉得多做做题就理解了, 而且这个也挺套路的.
代码
class Solution {public int[] dailyTemperatures(int[] temperatures) {int[] answer = new int[temperatures.length];//声明单调栈 空间换时间Deque<Integer> stack=new LinkedList<>();//先把第一个元素加入栈里stack.push(0);for (int i = 1; i < temperatures.length; i++) {//元素 i 比栈顶元素小 或相等 都应该压入if (temperatures[i] <= temperatures[stack.peek()]) {stack.push(i);} else {//如果元素i比栈顶元素大,就要记录结果并弹出栈顶, 继续比较,直到没有栈顶元素大while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {int index = stack.pop();answer[index] = i - index;}stack.push(i);}}return answer;}
}
496.下一个更大元素 I
本题和 739. 每日温度 看似差不多,其实 有加了点难度。
https://programmercarl.com/0496.%E4%B8%8B%E4%B8%80%E4%B8%AA%E6%9B%B4%E5%A4%A7%E5%85%83%E7%B4%A0I.html
第一印象
试了试,我有点迷糊.
看题解吧, 我真绕进去了.
我写的 num1 的元素 在 num2 中的位置是这么写的, 但卡哥说要用 map.
for (int i = 0; i < nums1.length; i++) {//num1里当前的元素int cur = nums1[i];int indexInNum2 = -1;//找到当前元素在num2里的下标for (int j = 0; j < nums2.length; j++) {if (nums2[j] == cur) {indexInNum2 = j;}}}
看完题解的思路
先用 map 记录 num1 中元素的值和下标,值为Key,下标为value
这样我们就可以只对 num2 做经典的单调栈操作, 如果我要pop的那个下标在map里, 就要记录结果.
//如果拿来的元素 i 比栈顶元素更大, 持续比较while (!stack.isEmpty() && nums2[i] > nums2[stack.peek()]) {int index = stack.pop();int cur = nums2[index];//如果弹出的元素是在map里的(nums1里的),就要记录结果//如果不是nums1里的,只弹出就可以了if (map.containsKey(cur)) {//res[在nums1里的下标] = 下一个更大的数值.res[map.get(cur)] = nums2[i];}}//拿来的元素 i 在比较之后, 一定要push进栈.stack.push(i);
就是比较绕, 一会是下标, 一会是元素.
每日温度是, 对于 每一个找到了更大的元素都 pop并记录结果到result里.
这道题是, 对于每一个找到了更大的元素都pop, 但只有在nums1(在map)里的才记录到结果result里.
实现中的困难
没有
感悟
用map来不被绕进去, 解决单调栈套的这个壳子.
还是实现能力不够啊
代码
class Solution {public int[] nextGreaterElement(int[] nums1, int[] nums2) {HashMap<Integer, Integer> map = new HashMap<>();//num1中值为Key, 下标为Valuefor (int i = 0; i < nums1.length; i++) {map.put(nums1[i], i);}int[] res = new int[nums1.length];Deque<Integer> stack = new LinkedList<>();//先都初始化为 -1.Arrays.fill(res, -1);stack.push(0);for (int i = 1; i < nums2.length; i++) {if (nums2[i] <= nums2[stack.peek()]) {stack.push(i);} else {//如果拿来的元素 i 比栈顶元素更大, 持续比较while (!stack.isEmpty() && nums2[i] > nums2[stack.peek()]) {int index = stack.pop();int cur = nums2[index];//如果弹出的元素是在map里的(nums1里的),就要记录结果//如果不是nums1里的,只弹出就可以了if (map.containsKey(cur)) {//res[在nums1里的下标] = 下一个更大的数值.res[map.get(cur)] = nums2[i];}}//拿来的元素 i 在比较之后, 一定要push进栈.stack.push(i);}}return res;}
}
相关文章:
Day49 力扣单调栈 : 739. 每日温度 |496.下一个更大元素 I
Day49 力扣单调栈 : 739. 每日温度 |496.下一个更大元素 I 739. 每日温度第一印象看完题解的思路什么是单调栈?我的总结 实现中的苦难感悟代码 496.下一个更大元素 I第一印象看完题解的思路实现中的困难感悟代码 739. 每日温度 今天正式开始单调栈,这是…...

实用篇-ES-RestClient查询文档
一、快速入门 上面的查询文档都是依赖kibana,在浏览器页面使用DSL语句去查询es,如何用java去查询es里面的文档(数据)呢 我们通过match_all查询来演示基本的API,注意下面演示的是 match_all查询,也叫基础查询 首先保证你已经做好了…...
2023年第九届数维杯国际大学生数学建模挑战赛
2023年第九届数维杯国际大学生数学建模挑战赛正在火热进行,小云学长又在第一时间给大家带来最全最完整的思路代码解析!!! 下面是数维杯B题思路解析: 前面三问主要是绘制趋势图、散点图等这些比较简单的统计学分析方法…...

TensorRT基础知识及应用【学习笔记(十)】
这篇博客为修改过后的转载,因为没有转载链接,所以选了原创 文章目录 一、准备知识1.1 环境配置A. CUDA DriverB. CUDAC. cuDNND. TensorRT 1.2 编程模型 二、构建阶段2.1 创建网络定义2.2 配置参数2.3 生成Engine2.4 保存为模型文件2.5 释放资源 三、运…...

[内存泄漏][PyTorch](create_graph=True)
PyTorch保存计算图导致内存泄漏 1. 内存泄漏定义2. 问题发现背景3. pytorch中关于这个问题的讨论 1. 内存泄漏定义 内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致…...

【Git学习二】时光回溯:git reset和git checkout命令详解
😁 作者简介:一名大四的学生,致力学习前端开发技术 ⭐️个人主页:夜宵饽饽的主页 ❔ 系列专栏:Git等软件工具技术的使用 👐学习格言:成功不是终点,失败也并非末日,最重要…...

多维时序 | MATLAB实现PSO-GRU-Attention粒子群优化门控循环单元融合注意力机制的多变量时间序列预测
多维时序 | MATLAB实现PSO-GRU-Attention粒子群优化门控循环单元融合注意力机制的多变量时间序列预测 目录 多维时序 | MATLAB实现PSO-GRU-Attention粒子群优化门控循环单元融合注意力机制的多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MAT…...
MySQL缓冲池的优化与性能提升
“不积跬步,无以至千里。” MySQL是许多Web应用的核心数据库,而数据库的性能对于应用的稳定运行至关重要。在MySQL中,缓冲池(Buffer Pool)是一个关键的组件,它直接影响着数据库的性能和响应速度。今天这篇文…...

一些RLHF的平替汇总
卷友们好,我是rumor。 众所周知,RLHF十分玄学且令人望而却步。我听过有的小道消息说提升很大,也有小道消息说效果不明显,究其根本还是系统链路太长自由度太高,不像SFT一样可以通过数据配比、prompt、有限的超参数来可控…...
7.docker部署前端vue项目,实现反向代理配置
介绍: 构建镜像:通过docker构建以nginx为基础的镜像,将vue项目生成的dist包拷贝至nginx目录下,.conf文件做反向代理配置;部署服务:docker stack启动部署服务; 通过执行两个脚本既可以实现构建…...

字符串函数详解
一.字母大小写转换函数. 1.1.tolower 结合cppreference.com 有以下结论: 1.头文件为#include <ctype.h> 2.使用规则为 #include <stdio.h> #include <ctype.h> int main() {char ch A;printf("%c\n",tolower(ch));//大写转换为小…...

Mybatis学习笔记-映射文件,标签,插件
目录 概述 mybatis做了什么 原生JDBC存在什么问题 MyBatis组成部分 Mybatis工作原理 mybatis和hibernate区别 使用mybatis(springboot) mybatis核心-sql映射文件 基础标签说明 1.namespace,命名空间 2.select,insert&a…...

【C++】模板初阶 【 深入浅出理解 模板 】
模板初阶 前言:泛型编程一、函数模板(一)函数模板概念(二)函数模板格式(三)函数模板的原理(四)函数模板的实例化(五)模板参数的匹配原则 三、类模…...

无需API开发,伯俊科技实现电商与客服系统的无缝集成
伯俊科技的无代码开发实现系统连接 自1999年成立以来,伯俊科技一直致力于为企业提供全渠道一盘货的服务。凭借其24年的深耕零售行业的经验,伯俊科技推出了一种无需API开发的方法,实现电商系统和客服系统的连接与集成。这种无代码开发的方式不…...

Python | 机器学习之逻辑回归
🌈个人主页:Sarapines Programmer🔥 系列专栏:《人工智能奇遇记》🔖少年有梦不应止于心动,更要付诸行动。 目录结构 1. 机器学习之逻辑回归概念 1.1 机器学习 1.2 逻辑回归 2. 逻辑回归 2.1 实验目的…...

手机,蓝牙开发板,TTL/USB模块,电脑四者之间的通讯
一,意图 通过手机蓝牙连接WeMosD1R32开发板,开发板又通过TTL转USB与电脑连接.手机通过蓝牙控制开发板上的LED灯的开,关,闪等动作,在电脑上打开串口监视工具观察其状态.也可以通过电脑上的串口监视工具来控制开发板上LED灯的动作,而在手机蓝牙监测工具中显示灯的状态. 二,原料…...

Springboot更新用户头像
人们通常(为徒省事)把一个包含了修改后userName的完整userInfo对象传给后端,做完整更新。但仔细想想,这种做法感觉有点二,而且浪费带宽。 于是patch诞生,只传一个userName到指定资源去,表示该请求是一个局部更新&#…...

Express.js 与 Nest.js对比
Express.js 与 Nest.js对比 自从 Node.js 发布以来,Javascript 在后端领域的使用有所增加。由于 Node.js 的使用越来越多,每天都会有新的框架和工具发布。Express 和 Nest 是使用 Node.js 创建后端应用程序的最著名的框架之一,在本文中&…...

总结 CNN 模型:将焦点转移到基于注意力的架构
一、说明 在计算机视觉时代,卷积神经网络(CNN)几十年来一直是主导范式。直到 2021 年 Vision Transformers (ViTs) 出现,这个领域才开始发生变化。现在,是时候采用受 Transformer 架构启发的基于注意力的模型了&#x…...

2023.11.16 hivesql高阶函数之开窗函数
目录 1.开窗函数的定义 2.数据准备 3.开窗函数之排序 需求:用三种排序方法查询学生的语文成绩排名,并降序显示 4.开窗函数分组 需求:按照科目来分类,使用三种排序方式来排序学生的成绩 5.聚合函数与分组配合使用 6.聚合函数同时和分组以及排序关键字配合使用 --需求1&…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...