刷爆力扣之第三大的数

news2024/12/23 3:21:57

刷爆力扣之第三大的数

HELLO,各位看官大大好,我是阿呆 🙈🙈🙈
今天阿呆继续记录下力扣刷题过程,收录在专栏算法中 😜😜😜

请添加图片描述

该专栏按照不同类别标签进行刷题,每个标签又分为 Easy、Medium、Hard 三个等级 👊👊👊

本部分所有题目均来自于LeetCode 网,并于每道题目下标明具体力扣网原题链接 🏃🏃🏃

OK,兄弟们,废话不多直接上题,冲冲冲 🌞🌞🌞


一 🏠 题目描述

414. 第三大的数

给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。

示例 1:

输入:[3, 2, 1]
输出:1
解释:第三大的数是 1 。

示例 2:

输入:[1, 2]
输出:2
解释:第三大的数不存在, 所以返回最大的数 2 。

示例 3:

输入:[2, 2, 3, 1]
输出:1
解释:注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。
此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1 。

提示:

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1

进阶:你能设计一个时间复杂度 O(n) 的解决方案吗?


二 🏠破题思路

2.1 🚀 关键信息

解决问题第一步,当然先提取题目字面上的关键信息 😎😎😎

题干很容易理解,就是返回此数组中 第三大的数 🌸🌸🌸


提取完题目中的关键信息后,直接进入第二阶段,思路整理 😃😃😃


2.2 🚀 思路整理

分类讨论法

定义数组的前三大的值,遍历数组会遇到以下三种情况

① 当前值比最大值大,则改变前大三的值

② 当前值比最大值小,比中间值大,则改变第二大和第三大两个值

③ 当前值比最小值大,则仅改变第三的值

返回时判断第三大值是否为 LONG_MIN ,若为则返回第一大值,否则返回第三大值 🌺🌺🌺


整理完解题思路后,直接进入第三阶段,代码实现 😃😃😃


三 🏠 代码详解

3.1 🚀 代码实现

按照我们刚才的破题思路,直接代码走起来 👇👇👇👇

int thirdMax(std::vector<int> nums) {
        //使用三个元素,且值为 LONG_MIN (一定比输入的 int 小)
        //极值替代这点没有想到, 使用三个元素这点也没有想到
        long firstNum = LONG_MIN, secondNum = LONG_MIN, thirdNum = LONG_MIN;

        //因为输入的一定比极值小,所以只有三个条件满足则走各个分支即可
        for (int index = 0; index < nums.size(); ++index){
            if (nums[index] > firstNum){ //比最大值大,则改变三个值
                thirdNum = secondNum;
                secondNum = firstNum;
                firstNum = nums[index];
            } else if (nums[index] < firstNum && nums[index] > secondNum) { //比中间值大,则改变两个值
                thirdNum = secondNum;
                secondNum = nums[index];
            } else if (nums[index] > thirdNum && nums[index] < secondNum){ //比最小值大,则改变一个值
                thirdNum = nums[index];
            }
        }
    
        return  thirdNum == LONG_MIN ? firstNum : thirdNum;  //判断结果是否存在第三大的值
    }

3.2 🚀 细节解析

看完 👀👀👀 全注释版的代码实现后,相信看官大大对整体逻辑已经是大写的 OK 了 😃😃😃

那么我们挖掘上述实现的晦涩细节 😖😖😖 进行解析,直接开干,走起来 👇👇👇👇

thirdNum == LONG_MIN ? firstNum : thirdNum //判断结果是否存在第三大的值

返回时判断第三大值是否为 LONG_MIN ,若为则返回第一大值,否则返回第三大值 🐳🐳🐳


四 🏠 心路历程

为方便各位看官大大了解博主真实刷题过程,我把当时状态纯纯真实还原,记录在心路历程这一小节,不感兴趣的小伙伴可以直接跳过哈

博主在第一阶段提取 🚀 关键信息没有问题,在第二阶段 🚀 思路整理没有问题

未考虑的点已在上述代码注释提到了,实现方式效率和简洁性太差 😭😭😭 ,代码如下 👇👇👇👇

int thirdMax(std::vector<int> nums) {
    std::list<int> threeElemArray = {nums[0]}; //把当前值当做最大值

    //遍历输入数组
    for (int index = 1; index < nums.size(); ++index) { // index 的范围是 [1,nums.size()) 数组下标是从 0 开始的
        std::list<int>::iterator threeElemArrayIter = threeElemArray.begin(); //拿到迭代器
        if (nums[index] == *threeElemArrayIter || nums[index] == *threeElemArray.rbegin()) continue; //如果三元素组

        if (nums[index] > *threeElemArrayIter) {	//如果当前值大于三元素组最大值
            threeElemArray.push_front(nums[index]); //直接插入三元素组的头
        } else if (nums[index] < *threeElemArray.rbegin()) { //如果当前值小于三元素组最大值
            threeElemArray.insert(threeElemArray.end(), nums[index]);  //直接插入三元素组的尾
        } else {
            if (nums[index] == *(++threeElemArrayIter)) continue;

            //走到这个分支说明当前三元素值大小至少为 2
            if (nums[index] > *threeElemArrayIter) { //大于第二
                threeElemArray.insert(threeElemArrayIter, nums[index]); //插在第二前面
            } else { //小于第二,考虑是否大于第三,走到这个分支说明大于第三
                threeElemArray.insert(++threeElemArrayIter, nums[index]); //插在第二后面
            } 
        }

        if (threeElemArray.size() > 3) threeElemArray.pop_back(); //删除最后元素
    }

    //如果第三大数不存在,则返回数组中最大的数
    return  threeElemArray.size() != 3 ? *(threeElemArray.begin()) : *(threeElemArray.rbegin()); //rend 是在头的位置, ++ 会内存越界
}

五 🏠 结语

身处于这个浮躁的社会,却有耐心看到这里,你一定是个很厉害的人吧 👍👍👍

如果各位看官大大觉得文章有帮助的话,别忘了点赞 + 关注哦,你们的鼓励就是我最大的动力

博主还会不断更新更优质的内容,加油吧!技术人! 💪💪💪

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

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

相关文章

(四)Spring Security Oauth2.0 源码分析--客户端端鉴权(token校验)

一 引言 在上篇文章我们分析了token的获取过程,那么拿到token后,将token放在请求头中进行资源的访问,客户端是如如何对token进行解析的呢,本文带你走进token校验的源码解析,基本流程如下所示 客户端向资源服务器发起请求时,在请求头Authorization携带申请的token请求被Filte…

网络编程——BIO与NIO介绍与底层原理

BIO BIO(Blocking IO) 又称同步阻塞IO&#xff0c;一个客户端由一个线程来进行处理 当客户端建立连接后&#xff0c;服务端会开辟线程用来与客户端进行连接。以下两种情况会造成IO阻塞&#xff1a; 服务端会一直阻塞&#xff0c;直到和客户端进行连接客户端也会一直阻塞&…

CPP 核心编程9-STL

STL初识 2.1 STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升大多情况下&#xff0c;数据结构和算法都未能有一套标准,导致被迫从事大量重复工作为了建立数据结构和算法的一套标准,诞生了S…

四、文件管理(二)目录

目录 2.0文件控制块和索引结点 2.1目录的结构 2.1.1单级目录结构 2.1.2两级目录结构 2.1.3树形目录结构 2.1.4有向无环图目录结构 2.2目录的操作 2.4文件共享 2.4.1基于索引结点&#xff08;硬链接&#xff09; 2.4.2基于符号链&#xff08;软链接&#xff09; 2.0文…

前端开发是做什么的?工作职责

想要了解前端从业者的工作职责&#xff0c;需要从一个完整网站应用产生流程入手&#xff0c;一个网站应用从无到有的过程大致如下 &#xff1a; 1&#xff09;产品经理与甲方反复沟通交流&#xff0c;逐步确定产品需求完成设计草图&#xff1b; 2&#xff09;产品经理根据需求…

如何在centos上安装nvidia docker

当基于nvidia gpu开发的docker镜像在实际部署时&#xff0c;需要先安装nvidia docker。那么如何安装nvidia docker呢。下面将详细介绍下。 安装原生docker yum -y install docker-io 下载nvidia docker安装包 我下载的是rpm文件&#xff0c;具体见截图 安装nvidia docker…

word如何给论文加引用文献

给论文加引用文献其实差不多就是加了个链接&#xff0c;通过点击链接跳转到文末最后展示引用文献额作者&#xff0c;论文名等等信息&#xff0c;给论文加引用文献只要有一下几步&#xff1a; 一、设置参考文献标号字体格式 对于论文中的文献&#xff0c;首先设置论文前序号的…

redis基础6——缓存穿透、缓存击穿、缓存雪崩

文章目录一、缓存穿透&#xff08;双库为空&#xff09;1.1 基础概念1.2 解决办法1.2.1 业务层校验1.2.2 设置key过期时间1.2.3 布隆过滤器1.2.3.1 原理1.2.3.1.1 哈希函数使用1.2.3.1.2 布隆过滤器数据结构1.2.3.1.2.1 映射函数执行过程1.2.3.1.2.2 布隆过滤器的误判率1.2.3.2…

华为机试 - 最大化控制资源成本

目录 题目描述 输入描述 输出描述 用例 题目解析 算法源码 题目描述 公司创新实验室正在研究如何最小化资源成本&#xff0c;最大化资源利用率&#xff0c;请你设计算法帮他们解决一个任务混部问题&#xff1a; 有taskNum项任务&#xff0c;每个任务有开始时间&#xf…

数字图像处理实验(一)|图像的基本操作和基本统计指标计算

文章目录一、实验目的二、实验主要仪器设备三、实验原理(1)将一幅图像视为一个二维矩阵。(2)利用MATLAB图像处理工具箱读、写和显示图像文件。(3)计算图像的有关统计参数。(4)改变图像尺寸、旋转图像、裁剪图像四、实验内容(1)用imwrite写入图像(2) 用imread读入一幅图像(自选)…

opencv c++ 图像形态学操作

1、图像的形态学操作 包括图像的腐蚀、膨胀、开、闭、形态学梯度、顶帽、黑帽、分支主题、结构元素等操作。 具体概念参考&#xff1a;(41条消息) 图像处理-形态学处理_Gooddz的博客-CSDN博客_图像处理 形态学 1.1、膨胀 用33的核去扫描二值图像&#xff0c;当核与图像中的前景…

[附源码]JAVA毕业设计仟侬堂茶具网站(系统+LW)

[附源码]JAVA毕业设计仟侬堂茶具网站&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&a…

LeetCode中等题之查找和替换模式

题目 你有一个单词列表 words 和一个模式 pattern&#xff0c;你想知道 words 中的哪些单词与模式匹配。 如果存在字母的排列 p &#xff0c;使得将模式中的每个字母 x 替换为 p(x) 之后&#xff0c;我们就得到了所需的单词&#xff0c;那么单词与模式是匹配的。 &#xff0…

Git(第二篇)——Git的常见操作

Git&#xff08;第二篇&#xff09;——Git的常见操作 目录Git&#xff08;第二篇&#xff09;——Git的常见操作一、Git版本控制介绍组成结构图命令速查常用命令二、下载并安装GIT设置字体查询git三、码云上的操作码云配置环境注册账号登录码云创建仓库创建远程仓库(在码云官网…

通讯录管理系统

目录 1.系统需求 2.创建项目 3.菜单功能 4.退出功能 5.添加联系人 5.1设计联系人结构体、设计通讯录结构体 5.2main函数中创建通讯录 5.3封装添加联系人函数 5.4测试添加联系人 6.显示联系人 7.删除联系人 7.1封装检测联系人是否存在 7.2删除联系人&#xff0c;测试删除联…

当我们的执行 java -jar xxx.jar 的时候底层到底做了什么?

大家都知道我们常用的 SpringBoot 项目最终在线上运行的时候都是通过启动 java -jar xxx.jar 命令来运行的。 那你有没有想过一个问题&#xff0c;那就是当我们执行 java -jar 命令后&#xff0c;到底底层做了什么就启动了我们的 SpringBoot 应用呢&#xff1f; 或者说一个 S…

Redux使用详解(一) Redux的核心思想与基本使用

Redux 理解javascript纯函数 函数式编程中有一个非常重要的概念叫纯函数&#xff0c;JavaScript符合函数式编程的范式&#xff0c;所以也有纯函数的概念&#xff1b; 在react开发中纯函数是被多次提及的&#xff1b; 比如react中组件就被要求像是一个纯函数&#xff08;为什么…

使用STM32F103C8T自制freejoy控制板

1. 软件准备 1.1 STM公司的官方工具&#xff1a; STM32 ST-LINK Utility 已经更名为 STM32CubeProgrammer STSW-LINK004 - STM32 ST-LINK utility (replaced by STM32CubeProgrammer) - STMicroelectronics 1.2 FreeJoyConfiguratorQt V1.7.1 这个是刷好固件后的配置、调…

D-025 DP硬件电路设计

DP硬件电路设计1 简介1.1 DP接口分类1.2 DP接口和HDMI接口的区别1.3 DP接口的优势2 硬件层3 接口定义4 原理图设计1 简介 Display是一种新型的标准化的数字式视频接口标准&#xff0c;其支持的功能与HDMI相似&#xff0c;但是其目标是作为HDMI的补充&#xff0c;而非取代。DP …

红队渗透靶场之SickOs1.1

靶场考察知识 shellshock漏洞 shellshock即unix系统下的bash shell的一个漏洞, Bash 4.3以及之前的版本在处理某些构造的环境变量时存在安全漏洞, 向环境变量值内的函数定义后添加多余的字符串会触发此漏洞, 攻击者可利用此漏洞改变或绕过环境限制&#xff0c;以执行任意的sh…