【代码随想录day48】【C++复健】739. 每日温度;496.下一个更大元素 I;503.下一个更大元素II

news2024/12/23 18:10:19

739. 每日温度

一顿操作猛如虎,一看击败5%。一眼顶针,鉴定为在存栈的时候把值和下标一起存了,所以导致了问题。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<vector<int>> temp;
        int n = temperatures.size();
        vector<int> result(n);
        for(int i=0; i<n; i++){
            while(!temp.empty() && temperatures[i] > temp.top()[0]){
                int pos = temp.top()[1];
                result[pos] = i - pos;
                temp.pop();
            }
            temp.push(vector<int> {temperatures[i], i});
        }
        return result;
    }
};

果然如此,改完之后就对了,击败93.07%。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<int> temp;
        int n = temperatures.size();
        vector<int> result(n);
        for(int i=0; i<n; i++){
            while(!temp.empty() && temperatures[i] > temperatures[temp.top()]){
                int pos = temp.top();
                result[pos] = i - pos;
                temp.pop();
            }
            temp.push(i);
        }
        return result;
    }
};

496.下一个更大元素 I

虽然卡哥说只是加了一点难度,但实际上变量一变多,我的脑子立刻就不够用了,接连犯错。每一层下标取完,出来对应什么含义,脑子一下就不清醒了。

做完之后看了下解析,我的做法和卡哥的做法还不太一样,具体区别体现在哈希表的建立方法上。

我的代码:

1 哈希map怎么插入值忘了。

想了半天是push还是append还是啥,最后一看答案,答案说直接通过键值的方式添加:nextbig[nums2[pos]] = nums2[i]。难怪我想不出来是什么关键词。

2 在往单调栈里面压入值的时候,应该压入的是下标而不是元素值!

写的时候整个人昏头了,写了个添加元素值的代码。

3 这里讲到的“下一个单调元素”就说的不是哪一个元素了,而是元素的值。

这一点和上一题是不一样的,小小的坑了我一下。我直接nextbig[nums2[pos]] = i;了。但这里才应该写元素值,而非下标。

4 没写找不到下一个更大元素时的处理逻辑。

其实也不算难,加上一个爆搜去找找看就行了。但是我还是第一时间没想出来的。我想的是nextbig[nums1[j]] == 0,因为未经赋值初始化是0,但这样写如果刚好有一个元素的值是0的话还是会出问题的,所以还是得用搜索。

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        unordered_map<int, int> nextbig;
        stack<int> numnum;
        for(int i=0; i<n; i++){
            while(!numnum.empty() && nums2[numnum.top()] < nums2[i]){
                int pos = numnum.top();
                nextbig[nums2[pos]] = nums2[i];
                numnum.pop();
            }
            numnum.push(i);
        }
        vector<int> result;
        for(int j=0; j<m; j++){
            if (nextbig.find(nums1[j]) == nextbig.end()) {
                result.push_back(-1);
            }
            else{
                result.push_back(nextbig[nums1[j]]);
            }
        }
        return result;
    }
};

卡哥的代码:

与我的代码的区别在于哈希表的建立方式,我的方法建立了nums2中的元素和对应的下一个更大元素之间的哈希关系,而卡哥的方法建立的是nums1和nums2之间的哈希关系。整体思路上应该是差不多的。

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        stack<int> st;
        vector<int> result(nums1.size(), -1);
        if (nums1.size() == 0) return result;

        unordered_map<int, int> umap; // key:下标元素,value:下标
        for (int i = 0; i < nums1.size(); i++) {
            umap[nums1[i]] = i;
        }
        st.push(0);
        for (int i = 1; i < nums2.size(); i++) {
            while (!st.empty() && nums2[i] > nums2[st.top()]) {
                if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素
                    int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标
                    result[index] = nums2[i];
                }
                st.pop();
            }
            st.push(i);
        }
        return result;
    }
};

看了解析感觉它的这个代码里面有些比我的还要绕,比如这个:
int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标
result[index] = nums2[i];

就让我看了半天,我们挨个说:
1 st.top()表示栈顶元素,栈里面存的是nums2当中每个元素对应的下标。

2 nums2[st.top()]将nums2当中每个元素对应的下标还原为元素的值。

3 umap[nums2[st.top()]]找到nums1当中,和当前nums2的值相等的元素的下标。

4 result[index]表示根据找到的nums1当中下标的位置,将nums2[i](下一个最大元素的值)赋给它。

属实是有点难度,光看了理解就比较难了,写出来就更是难上加难了。

503.下一个更大元素II

因为感觉如果写一个循环然后还要去分大于n和小于n的情况进行分别处理,个人感觉直接把同一个代码重复两遍即可,所以挥挥手写出如下代码:

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int n = nums.size();
        stack<int> st;
        vector<int> result(n);
        for(int i=0; i<n; i++){
            while(!st.empty() && nums[st.top()] < nums[i]){
                int pos = st.top();
                result[pos] = nums[i];
                st.pop();
            }
            st.push(i);
        }
        for(int i=0; i<n; i++){
            while(!st.empty() && nums[st.top()] < nums[i]){
                int pos = st.top();
                result[pos] = nums[i];
                st.pop();
            }
            st.push(i);
        }
        while(!st.empty()){
            int pos = st.top();
            result[pos] = -1;
            st.pop();
        }
        return result;
    }
};

还以为这么写必然是万无一失的,没想到看了眼结果,两次循环竟然与一次循环的返回值一模一样。经过了两分半的研究,终于发现问题出在最后一个循环这里:

看似好像没什么问题,但实际却并不是,我们第一遍循环的时候就把一些没找到更大值的压入了栈内,第二遍循环的时候虽然把第一遍时没找到,且存在更大元素的那些元素给弹了出来,但是后面又加进去了!那此时再出栈并且赋值为-1,明明找到的正确答案又被-1覆盖回去了。

while(!st.empty()){
    int pos = st.top();
    result[pos] = -1;
    st.pop();
}

那怎么办呢?两个办法:

1 赋值改成vector<int> result(n, -1);

此时我们发现,后面这个循环不用跑了,里面有一个还是有两个也不重要了。

2 在第二次循环里注释掉st.push(i);

为什么可以这么做?请看GPT:

简单来说就是,第二次遍历实际只是处理第一次遍历时的剩余元素,因此第二次遍历完全不需要再去插入新的元素。 

看了卡哥解析之后发现可以写成i % nums.size(),只能说学到了。确实这样就不需要去分前n和后n讨论了,一点也不用担心写的麻烦的问题。并且GPT里面还写成了int num = nums[i % n];,这样后面只要用num这样简单的三个字母就能代替nums[i % nums.size()]这一大串。这种怎么让自己写的更舒服的办法还是要好好学习的。

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

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

相关文章

vscode + conda + qt联合开发

安装vscode 安装conda 清华大学开源软件镜像(Anaconda下载)_清华大学镜像-CSDN博客 conda create新建一个环境&#xff0c;激活这个环境&#xff0c;然后安装pyside6 pip install pyside6 -i https://pypi.tuna.tsinghua.edu.cn/simple 安装成功后输入 pip list查看是否安装…

第十一篇 绘图matplotlib.pyplot的使用

文章目录 摘要安装方法入门案例使用plt绘图使用ax绘图plt.figure参数plot参数案例一 绘制红色实心的点状图案例二 绘制红色的破折线图案例三 绘制两条线颜色总结设置标题、轴名称、图例使用plt实现绘图使用ax实现绘图legend()中loc设置刻度plt自定义刻度ax自定义刻度plt.title …

Unity-Particle System属性介绍(一)基本属性

什么是ParticleSystem 粒子系统是Unity中用于模拟大量粒子的行为的组件。每个粒子都有一个生命周期&#xff0c;包括出生、运动、颜色变化、大小变化和死亡等。粒子系统可以用来创建烟雾、火焰、水、雨、雪、尘埃、闪电和其他各种视觉效果。 开始 在项目文件下创建一个Vfx文件…

计算机的错误计算(一百七十二)

摘要 探讨 MATLAB 对于算式 的计算误差。 例1. 在 MATLAB 中计算 的值。 直接贴图吧&#xff1a; 这样&#xff0c;MATLAB 的输出中只有3位正确数字&#xff0c;有效数字的错误率为 (16-3)/16 81.25% . 因为16位的正确输出为 0.2971242332737277e-18&#xff08;ISReals…

Flink四大基石之CheckPoint(检查点) 的使用详解

目录 一、Checkpoint 剖析 State 与 Checkpoint 概念区分 设置 Checkpoint 实战 执行代码所需的服务与遇到的问题 二、重启策略解读 重启策略意义 代码示例与效果展示 三、SavePoint 与 Checkpoint 异同 操作步骤详解 四、总结 在大数据流式处理领域&#xff0c;Ap…

S4 UPA of AA :新资产会计概览

通用并行会计&#xff08;Universal Parallel Accounting&#xff09;可以支持每个独立的分类账与其他模块集成&#xff0c;UPA主要是为了支持平行评估、多货币类型、财务合并、多准则财务报告的复杂业务需求 在ML层面UPA允许根据不同的分类账规则对物料进行评估&#xff0c;并…

Vue3学习宝典

1.ref函数调用的方式生成响应式数据&#xff0c;可以传复杂和简单数据类型 <script setup> // reactive接收一个对象类型的数据 import { reactive } from vue;// ref用函数调用的方式生成响应式数据&#xff0c;可以传复杂和简单数据类型 import { ref } from vue // 简…

Linux——基础命令(2) 文件内容操作

目录 ​编辑 文件内容操作 1.Vim &#xff08;1&#xff09;移动光标 &#xff08;2&#xff09;复制 &#xff08;3&#xff09;剪切 &#xff08;4&#xff09;删除 &#xff08;5&#xff09;粘贴 &#xff08;6&#xff09;替换,撤销,查找 &#xff08;7&#xff…

openwrt利用nftables在校园网环境下开启nat6 (ipv6 nat)

年初写过一篇openwrt在校园网环境下开启ipv6 nat的文章&#xff0c;利用ip6tables控制ipv6的流量。然而从OpenWrt22版本开始&#xff0c;系统内置的防火墙变为nftables&#xff0c;因此配置方法有所改变。本文主要参考了OpenWRT使用nftables实现IPv6 NAT 这篇文章。 友情提示 …

go语言的成神之路-筑基篇-gin框架渲染模板

第一节-gin框架渲染模板 因为电脑打不开了&#xff0c;所以用朋友的电脑来写的&#xff0c;也是体验了一次从零开始用vscode配置环境&#xff0c;忙活了一上午才配置好环境。太难配置了。好了废话不多说开始今天的进修之旅。 今天开始gin框架的正式学习希望大家认真观看并检查…

【软考网工笔记】网络基础理论——网络层

文章目录 中断处理过程数据包组装RIPRSVPipv4RIPv1 & RIPv2HFC 混合光纤同轴电缆&#xff08;Hybrid Fiber Coax&#xff0c;简称HFC&#xff09;BGP (边界网关协议)BGP-4 协议的四种报文ICMP 协议数字语音电子邮件协议MPLS 多协议标记交换ipv6DHCPDNS名称解析过程查询顺序…

linux网络抓包工具

linux网络抓包工具 一、tcpdump1.1 基本用法1.2 龙芯平台实例操作 二、wireshark2.1 主要功能2.2 龙芯平台实例操作 一、tcpdump tcpdump 指令可列出经过指定网络界面的数据包文件头&#xff0c;可以将网络中传送的数据包的 “头” 完全截获下来提供分析。它支持针对网络层、协…

NaviveUI框架的使用 ——安装与引入(图标安装与引入)

文章目录 概述安装直接引入引入图标样式库 概述 &#x1f349;Naive UI 是一个轻量、现代化且易于使用的 Vue 3 UI 组件库&#xff0c;它提供了一组简洁、易用且功能强大的组件&#xff0c;旨在为开发者提供更高效的开发体验&#xff0c;特别是对于构建现代化的 web 应用程序。…

WPF DataGrid 列隐藏

Window节点加上下面的 <Window.Resources><FrameworkElement x:Key"ProxyElement" DataContext"{Binding}" /></Window.Resources>然后随便加一个隐藏控件 <ContentControl Content"{StaticResource ProxyElement}" Visi…

【Gitlab】CICD使用minio作为分布式缓存

1、安装minio 下载适合自己系统版本的安装文件https://dl.min.io/server/minio/release/windows-amd64/ yum install xxx.rpm 2、配置/etc/profile export MINIO_ACCESS_KEYroot [ui登录账号] export MINIO_SECRET_KEYminioDev001 [ui登录密码] export MINIO_OPTS"…

用到动态库的程序运行过程

当我们写好了一段代码然后编译运行后会生成可执行文件&#xff0c;该文件会存在磁盘的当前目录下&#xff0c;而当我们开始运行这段程序时&#xff0c;操作系统&#xff08;加载器&#xff09;需要将其从磁盘加载进内存然后执行相关操作&#xff0c;而对于用到动态库的程序&…

ansible自动化运维(一)配置主机清单

目录 一、介绍 1.1了解自动化运维 1.2 ansible简介 1.3 ansible自动化运维的优势 1.4 ansible架构图 二、部署ansible 2.1 基本参数 2.2 Ansible帮助命令 2.3 配置主机清单 2.3.1 查看ansible的所有配置文件 2.3.2 /etc/ansible/ansible.cfg常用配置选项 2.3.3 ssh密…

高效集成:将聚水潭数据导入MySQL的实战案例

聚水潭数据集成到MySQL&#xff1a;店铺信息查询案例分享 在数据驱动的业务环境中&#xff0c;如何高效、准确地实现跨平台的数据集成是每个企业面临的重要挑战。本文将聚焦于一个具体的系统对接集成案例——将聚水潭的店铺信息查询结果集成到MySQL数据库中&#xff0c;以供BI…

Spark基本命令详解

文章目录 Spark基本命令详解一、引言二、Spark Core 基本命令1、Transformations&#xff08;转换操作&#xff09;1.1、groupBy(func)1.2、filter(func) 2、Actions&#xff08;动作操作&#xff09;2.1、distinct([numTasks])2.2、sortBy(func, [ascending], [numTasks]) 三、…

[在线实验]-ActiveMQ Docker镜像的下载与部署

镜像下载 下载ActiveMQ的Docker镜像文件。通常&#xff0c;这些文件会以.tar格式提供&#xff0c;例如activemq.tar。 docker的activemq镜像资源-CSDN文库 加载镜像 下载完成后&#xff0c;您可以使用以下命令将镜像文件加载到Docker中&#xff1a; docker load --input a…