代码随想录算法训练营第五十八天-单调栈1|739. 每日温度 496.下一个更大元素 I

news2024/11/26 18:40:44

739. Daily Temperatures

public class DailyTemperatures {
    //暴力解法
    public int[] dailyTemperatures(int[] T){
        int length = T.length;
        int[] result = new int[length];
        for(int i = 0; i < length; i++){
            int current = T[i];
            if(current < 100){
                for(int j = i + 1; j < length; j++){
                    if(T[j] > current){
                        result[i] = j - i;
                        break;
                    }
                }
            }
        }return result;
    }

思路

首先想到的当然是暴力解法,两层for循环,把至少需要等待的天数就搜出来了。时间复杂度是O(n^2)

那么接下来在来看看使用单调栈的解法。

739图解

那有同学就问了,我怎么能想到用单调栈呢? 什么时候用单调栈呢?

通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。

例如本题其实就是找找到一个元素右边第一个比自己大的元素,此时就应该想到用单调栈了。

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

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

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

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

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

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

  1. 单调栈里元素是递增呢? 还是递减呢?

注意以下讲解中,顺序的描述为 从栈头到栈底的顺序,因为单纯的说从左到右或者从前到后,不说栈头朝哪个方向的话,大家一定比较懵。

这里我们要使用递增循序(再强调一下是指从栈头到栈底的顺序),因为只有递增的时候,栈里要加入一个元素i的时候,才知道栈顶元素在数组中右面第一个比栈顶元素大的元素是i。

 

我们要保持一个递增单调栈(从栈头到栈底),所以将T[0]弹出(元素记录过就可以从栈里弹出),T[1]加入,此时result数组可以记录了,result[0] = 1,即T[0]右面第一个比T[0]大的元素是T[1]。

 

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

文字描述理解起来有点费劲,接下来我画了一系列的图,来讲解单调栈的工作过程,大家再去思考,本题为什么是递增栈。

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

  • 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况

把这三种情况分析清楚了,也就理解透彻了

 

 public int[] dailyTemperatures(int[] temperatures) {
        int lens = temperatures.length;
        int[]res = new int[lens];
        /**
         如果当前遍历的元素 大于栈顶元素,表示 栈顶元素的 右边的最大的元素就是 当前遍历的元素,
         所以弹出 栈顶元素,并记录
         如果栈不空的话,还要考虑新的栈顶与当前元素的大小关系
         否则的话,可以直接入栈。
         注意,单调栈里 加入的元素是 下标。
         */
        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);
        for(int i = 1;i < lens; i++){
            if(temperatures[i]<=temperatures[stack.peek()]){
                stack.push(i);
            }else{
                while(!stack.isEmpty()&&temperatures[i] >temperatures[stack.peek()]){
                    res[stack.peek()] = i - stack.peek();
                    stack.pop();
                }
                stack.push(i);
            }
        }
        return res;

496.下一个更大元素 I

1.数组nums1是nums2的子集,且各自没有重复的元素

2.求数组nums1里的元素在数组nums2里,这个元素,它的右边第一个比其大的元素,输出放入对应位置

思路:

1)从题目示例中我们可以看出最后是要求nums1的每个元素在nums2中下一个比当前元素大的元素,那么就要定义一个和nums1一样大小的数组result来存放结果。题目说如果不存在对应位置就输出 -1 ,所以result数组如果某位置没有被赋值,那么就应该是是-1,所以就初始化为-1

2)在nums2里找某元素大于右边第一个比他大元素数,所以遍历数组2.

3)nums1和nums2的联系,找到nums1[i] == nums2[j]对应的下标,用hashmap映射

4)单调栈是递增

import java.util.Arrays;
import java.util.HashMap;
import java.util.Stack;

public class NextGreaterElement1 {

    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        Stack<Integer> temp = new Stack<>();
        int[] res = new int[nums1.length];
        // To fill complete array with a particular value
        Arrays.fill(res, -1);
        //对nums1进行映射,用哈希表
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        for(int i = 0; i < nums1.length; i++){
            hashMap.put(nums1[i], i);
        }
        //用单调栈遍历数组2
        temp.add(0);
        for(int i = 1; i< nums2.length; i++){
            if(nums2[i] <= nums2[temp.peek()]){
                temp.add(i);
            }else{
                while (!temp.isEmpty()&& nums2[i] > nums2[temp.peek()]){
                    if(hashMap.containsKey(nums2[temp.peek()])){
                        //获取对应下标
                        Integer index = hashMap.get(nums2[temp.peek()]);
                        //结果更新
                        res[index] = nums2[i];
                    }
                    temp.pop();

                }
                temp.add(i);
            }
        }
        return res;


    }
}

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

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

相关文章

C++语法(13)---- 模拟实现priority_queue

C语法&#xff08;12&#xff09;---- 模拟实现queue和stack_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/130068637 目录 1.使用 2.模拟实现 1.数据元素 2.数据建立 3.函数实现 4.向上调整和向下调整 3.仿函数&#xff08;函数对象&…

【马蹄集】第五周作业

第五周作业 目录MT2030 邮箱地址MT2039 换换换MT2040 银行账户MT2041 三角形的个数MT2046 巨大的错误MT2030 邮箱地址 难度&#xff1a;钻石    时间限制&#xff1a;1秒    占用内存&#xff1a;128M 题目描述 一个地址由 <username><hostname>[/resource] …

DAY 34 正则表达式

正则表达式 REGEXP&#xff1a; Regular Expressions&#xff0c;由一类特殊字符及文本字符所编写的模式&#xff0c; 其中有些字符&#xff08;元字符&#xff09;不表示字符字面意义&#xff0c;而表示控制或通配的功能&#xff0c; 类似于增强版的通配符功能&#xff0c;但…

day13 信号机制 (上)

目录 信号的概念 信号的发送和定时器 信号的函数 定时器函数 信号的捕捉 信号的概念 概念&#xff1a; 信号是软件层次上对中断机制的一种模拟&#xff0c;是一种异步通信方式&#xff0c;所有信号的产生及处理都是有内核完成的。 信号的产生&#xff1a; 1、按键产生…

Excel常用函数公式20例

目录 一、【IF函数条件判断】 二、【多条件判断】 三、【条件求和】 四、【多条件求和】 五、【条件计数】 六、【多条件计数】 七、【条件查找】 八、【多条件查找】 九、【计算文本算式】 十、【合并多个单元格内容】 十一、【合并带格式的单元格内容】 十二、…

SpringBoot整合minio实现对象存储

分布式文件系统应用场景 互联网海量非结构化数据的存储需求电商网站&#xff1a;海量商品图片视频网站&#xff1a;海量视频文件网盘&#xff1a;海量文件社交网站&#xff1a;海量图片 minio的概念 Minio是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊…

淘宝天猫数据分析工具推荐(竞品数据监控查询)

在当前的电商环境下&#xff0c;天猫平台的商家非常多&#xff0c;且不同商家的营销策略、手段等都不尽相同。对于商家而言&#xff0c;面对庞大的竞争对手&#xff0c;做好对竞争对手的监控工作也是一个非常重要的课题。 商家做好竞品监控的好处有哪些呢&#xff1f; 1、做好竞…

想毕业我阿里P8测开?除非把整条业务线都裁了.我的底气何来?

简单介绍一下自己&#xff0c;某985硕士&#xff0c;现在阿里智能事业部&#xff0c;视频云中台&#xff0c;测试开发岗。年纪嘛&#xff0c;快接近你们说的去送外卖的年纪了。主要的工作职责是参与制定测试保障策略和建立测试保障体系&#xff0c;开发和维护定制的自动化测试工…

cm-14.1 Android系统启动过程分析(n)- 关机/重启/重置/升级的那些事(偏嵌入式方向)

声明 前阶段在项目中涉及到了Android系统定制任务,Android系统定制前提要知道Android系统是如何启动的。本文参考了一些书籍的若干章节。本文使用的代码是LineageOS的cm-14.1,对应Android 7.1.2,可以参考我的另一篇博客:如何下载Nexus5的LineageOS14.1(cm-14.1)系统源码并编…

Linux-初学者系列——篇幅3_操作界面获取帮助

操作界面获取帮助-目录1、获取帮助信息-man2、获取帮助信息-help3、获取帮助信息-info上篇: Linux-初学者系列——篇幅2_系统命令界面 利用帮助命令自学&#xff1a;man help info1、获取帮助信息-man 查看命令和部分文件帮助说明信息 使用方法&#xff1a; man [参数选项]…

Linux-系统大概介绍

桌面和终端基本使用 使用CtrlAlt可以取消状态&#xff0c;利于TabAlt切屏 在Linux中&#xff0c;WIN键是Super键 打开终端&#xff0c;终端有点像Windows的命令行&#xff0c;然后Ctrlaltf2可以切换为纯命令行&#xff0c;Ctrlalt是调出鼠标&#xff0c;Ctrlaltf1切回图形用户…

Unity使用webSocket与服务器通信(三)——C#服务端(Fleck)与Unity客户端( NativeWebSocket)传输多种数据数据

一、通信时会传输哪些内容 1、字符串数据 简单的字符串&#xff1a;比如登录请求信息&#xff0c;登录结果返回的信息。 用json系列化的字符串&#xff1a;比如上传一个表到服务器&#xff0c;让它写入到数据库中。 读取文件的时候&#xff0c;读取的是string内容。 2、二进制…

如何使用Midjourney自己设计独特的Logo,常用的提示和使用效果展示(内附Midjourney提示词网站)

文章目录一、提示技巧二、图案标志(图形)1.最小线条标志(Minimal Line Marks)2.渐变标志(Gradient Marks)3.中式标志&#xff08;Chinese Style Marks&#xff09;三、抽象/几何标志四、徽章设计五、吉祥物Logo六、平面设计七、其它一些Logo八、好用的Midjourney提示词网站生成…

Java通过继承的方法来实现长方形的面积和体积

目录 前言 一、测试.java类 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 二、Changfangxing.java类 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 三、Jxing.java类 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 1.3运行截图 前言 1.若有选择…

【通用篇】chrome调试技巧

一、前言 Google Chrome 是一款由 Google 公司开发的免费网页浏览器&#xff0c;它的特点是速度快、安全、简单易用。它的市场份额长期位居全球第一&#xff0c;受到了广泛的用户和开发者的欢迎。 Chrome DevTools 是 Chrome 浏览器内置的一组开发者工具&#xff0c;旨在帮助…

深度学习目标检测项目实战(四)—基于Tensorflow object detection API的骨折目标检测及其界面运行

深度学习目标检测项目实战(四)—基于Tensorflow object detection API的骨折目标检测及其界面运行 使用tensorflow object detection进行训练检测 参考原始代码&#xff1a;https://github.com/tensorflow/models/tree/master/research 我用的是1.x的版本 所以环境必须有gpu版…

初级算法-二叉树

主要记录算法和数据结构学习笔记&#xff0c;新的一年更上一层楼&#xff01; 初级算法-二叉树一、递归遍历二、迭代遍历三、统一迭代法四、层序遍历五、翻转二叉树六、对称二叉树七、二叉树的最大深度八、二叉树的最小深度九、完全二叉树的节点个数十、平衡二叉树十一、二叉树…

浅说黄河三门

黄河是一首雄浑的诗。 黄河是一幅神奇的画。 她从雪域高原走来&#xff0c;一路接百川、纳细流&#xff0c;穿山越岭。 在行至内蒙古托尧托县的河口镇时&#xff0c;骤然调头南下&#xff0c;滚滚河水如一把利剑&#xff0c;将偌大的黄土高原一劈两半。 在秦晋两省的边界线上…

网络安全自学笔记+岗位介绍

我就在这个行业&#xff0c;目前湖南&#xff0c;薪资就没必要说了&#xff0c;高就对了。 这个行业优势就是工资高&#xff0c;缺点就需要一直学&#xff0c;卷得要死&#xff0c;不是跟别人卷&#xff0c;而是自己卷&#xff0c;一会后面细说 这个行业目前分为几个岗位&#…

Hadoop之HBase

文章目录一、HBase简介二、HBase结构1.1HBase逻辑结构1.2HBase物理结构1.3HBase基础架构三、HBase安装配置3.1单机模式3.2集群搭建四、HBase JAVA API一、HBase简介 《HBase官方文档》的原文地址是&#xff1a;http://hbase.apache.org/book.html W3Cschool.cn进行整理翻译 ht…