【LeetCode215】数组中的第K个最大元素

题目地址

1. 基本思路

用一个基准数e将集合S分解为不包含e在内的两个小集合 S 1 S_{1} S1 S 2 S_{2} S2,其中 S 1 S_{1} S1的任何元素均大于等于e, S 2 S_{2} S2的任何元素均小于e,记 ∣ S ∣ |S| S代表集合S元素的个数,这样,如果 ∣ S 1 ∣ ≥ K |S_{1}|\ge K S1K,则说明第K大数在 S 1 S_{1} S1中;如果 ∣ S 1 ∣ |S_{1}| S1恰好等于K-1,说明e是第K大数;否则第K大数在 S 2 S_{2} S2中,并且是 S 2 S_{2} S2中的第 K − ∣ S 1 ∣ − 1 K-|S_{1}|-1 KS11大数。然后,可以用类似的思路继续在 S 1 S_{1} S1 S 2 S_{2} S2中查找。
其实这就是快速排序划分数组的过程

2. 最后一个巨型测试用例不通过的代码

//求划分
//其实这个方法就是快速排序求划分的过程
int divide(int* nums, int left, int right)
{//基准数e选nums[left],题目中的数组非空,不用判断特殊情况int e = nums[left];//接下来要把数组分成两部分,一部分小于e,一部分大于等于ewhile (left < right){//让right一直向左移动,直到找到比基准数e小的数,并让这个元素传入left的位置while (left < right && nums[right] >= e){right--;}nums[left] = nums[right];//让left一直向右移动,直到找到比基准数e大的数,并让这个元素传入right的位置while (left < right && nums[left] <= e){left++;}nums[right] = nums[left];}nums[left] = e; //基准数最终存放的位置return left; //返回基准数的新下标
}
//递归用的helper
int findKthLargestHelper(int* nums, int left, int right, int k)
{// 数组S1的元素都大于等于基准数e,但是S1不包括基准数e,先求出基准数的下标e_index// 数组S2就是0到S1_start - 1这些下标对应的元素int e_index = divide(nums, left, right);// 求出S1的长度(注意,S1不包括基准数e),right - e_index - 1 + 1即right - e_indexint len_S1 = right - e_index;// 如果S1长度大于kif (len_S1 >= k){//S1和S2都不包括基准数ereturn findKthLargestHelper(nums, e_index + 1, right, k);}else if (len_S1 < k - 1){return findKthLargestHelper(nums, left, e_index - 1, k - len_S1 - 1);}else //恰好S1长度为k-1,说明基准数是第k大的数{return nums[e_index];}
}
int findKthLargest(int* nums, int numsSize, int k) {//如果使用递归,最后一个巨大的测试用例无法通过,故使用循环int left = 0;int right = numsSize - 1;// 数组S1的元素都大于等于基准数e,但是S1不包括基准数e,先求出基准数的下标e_index// 数组S2就是0到S1_start - 1这些下标对应的元素int e_index = 0; //先初始化为0// 求出S1的长度(注意,S1不包括基准数e),right - e_index - 1 + 1即right - e_indexint len_S1 = 0; //先初始化为0while(left <= right){e_index = divide(nums, left, right);len_S1 = right - e_index;// 如果S1长度大于kif (len_S1 >= k){//就继续去S1数组中继续分割left = e_index + 1;//k值不变}else if (len_S1 < k - 1){//去S2数组中继续分割right = e_index - 1;//k值变化k = k - len_S1 - 1;}else{//恰好S1长度为k-1,说明基准数是第k大的数return nums[e_index];}}return nums[e_index];
}

正好卡在最后一个测试用例:

没通过的原因是,我们取的基准值不是从数组中选的随机值,接下来修改代码

3. 选用随机值的快速排序划分

//生成从x到y的整数随机数
int getIntRandom(int x, int y)
{// 传入时间戳,生成伪随机数srand((unsigned int)time(NULL));return (int)(x + (rand() % (y - x + 1)));
}
//求划分
//其实这个方法就是快速排序求划分的过程
int divide(int* nums, int left, int right)
{//随机选一个基准数的下标int random_index = getIntRandom(left, right);// 基准值int e = nums[random_index];// 将nums[random_index]和nums[left]互换,方便后来交换int temp = nums[random_index];nums[random_index] = nums[left];nums[left] = temp;//接下来要把数组分成两部分,一部分小于e,一部分大于等于ewhile (left < right){//让right一直向左移动,直到找到比基准数e小的数,并让这个元素传入left的位置while (left < right && nums[right] >= e){right--;}nums[left] = nums[right];//让left一直向右移动,直到找到比基准数e大的数,并让这个元素传入right的位置while (left < right && nums[left] <= e){left++;}nums[right] = nums[left];}nums[left] = e; //基准数最终存放的位置return left; //返回基准数的新下标
}
//递归用的helper
int findKthLargestHelper(int* nums, int left, int right, int k)
{// 数组S1的元素都大于等于基准数e,但是S1不包括基准数e,先求出基准数的下标e_index// 数组S2就是0到S1_start - 1这些下标对应的元素int e_index = divide(nums, left, right);// 求出S1的长度(注意,S1不包括基准数e),right - e_index - 1 + 1即right - e_indexint len_S1 = right - e_index;// 如果S1长度大于kif (len_S1 >= k){//S1和S2都不包括基准数ereturn findKthLargestHelper(nums, e_index + 1, right, k);}else if (len_S1 < k - 1){return findKthLargestHelper(nums, left, e_index - 1, k - len_S1 - 1);}else //恰好S1长度为k-1,说明基准数是第k大的数{return nums[e_index];}
}
int findKthLargest(int* nums, int numsSize, int k) {//如果使用递归,最后一个巨大的测试用例无法通过,故使用循环int left = 0;int right = numsSize - 1;// 数组S1的元素都大于等于基准数e,但是S1不包括基准数e,先求出基准数的下标e_index// 数组S2就是0到S1_start - 1这些下标对应的元素int e_index = 0; //先初始化为0// 求出S1的长度(注意,S1不包括基准数e),right - e_index - 1 + 1即right - e_indexint len_S1 = 0; //先初始化为0while(left <= right){e_index = divide(nums, left, right);len_S1 = right - e_index;// 如果S1长度大于kif (len_S1 >= k){//就继续去S1数组中继续分割left = e_index + 1;//k值不变}else if (len_S1 < k - 1){//去S2数组中继续分割right = e_index - 1;//k值变化k = k - len_S1 - 1;}else{//恰好S1长度为k-1,说明基准数是第k大的数return nums[e_index];}}return nums[e_index];
}

提交结果:

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

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

相关文章

JDBC常见的几种连接池使用(C3P0、Druid、HikariCP 、DBCP)

前言 数据库连接池负责分配、管理和释放数据库连接&#xff0c;它允许应用程序重复使用一个现有的数据库连接&#xff0c;而不是重新建立一个。连接池技术尽可能多地重用了消耗内存的资源&#xff0c;大大节省了内存。通过使用连接池&#xff0c;将大大提高程序运行效率。常用的…

Java——构造器(构造方法)和 this

一、什么是构造器 构造器&#xff08;Constructor&#xff09;是Java类的一种特殊方法&#xff0c;用于初始化对象的状态。构造器在创建对象时被调用&#xff0c;可以对对象的成员变量进行初始化。 我之前的文章《Java——类和对象-CSDN博客》中也提到了构造器。 二、构造器…

【面试题】MySQL常见面试题总结

备战实习&#xff0c;会定期给大家整理常考的面试题&#xff0c;大家一起加油&#xff01; &#x1f3af; 系列文章目录 【面试题】面试题分享之JVM篇【面试题】面试题分享之Java并发篇【面试题】面试题分享之Java集合篇&#xff08;三&#xff09; 注意&#xff1a;文章若有错…

AI办公自动化:批量在多个Word文档中插入对应图片

工作任务&#xff1a;文件夹中有多个word文档和word文档名称一致的图片&#xff0c;要把这些图片都插入到word文档中 在chatpgt中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;写一个Python脚本&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;F:…

蓝队-溯源技巧

溯源技巧 大致思想 通常情况下&#xff0c;接到溯源任务时&#xff0c;获得的信息如下 攻击时间 攻击 IP 预警平台 攻击类型 恶意文件 受攻击域名/IP其中攻击 IP、攻击类型、恶意文件、攻击详情是溯源入手的点。 通过攻击类型分析攻击详情的请求包&#xff0c;看有没有攻击者…

零基础入门学用Arduino 第三部分(二)

重要的内容写在前面&#xff1a; 该系列是以up主太极创客的零基础入门学用Arduino教程为基础制作的学习笔记。个人把这个教程学完之后&#xff0c;整体感觉是很好的&#xff0c;如果有条件的可以先学习一些相关课程&#xff0c;学起来会更加轻松&#xff0c;相关课程有数字电路…

8、项目目录结构创建

项目目录结构创建 8.1 三层架构 在spring-boot 的web项目中大都是按照这个思路来的: controller层 —> service层(serviceImpl实现service接口)—> mapper层—> mapper.xml文件 创建目录 commen:存放公共代码的 config:存放配置代码的 controller:后端控制器,…

长连接的钟表程序

实验要求 实现1个钟表程序&#xff08;服务&#xff09;&#xff0c;多个用户可以从该程序获得时间并在本地显示&#xff0c;用户也可以修改时间。 &#xff08;1&#xff09;用户程序可以在计算机上运行&#xff0c;也可以在手机上运行&#xff1b; &#xff08;2&#xff…

了解统计学中不同类型的分布

目录 一、说明 二、均匀分布&#xff1a; 三、机器学习和数据科学中的均匀分布示例&#xff1a; 3.1 对数正态分布&#xff1a; 3.2 机器学习和数据科学中的对数正态分布示例&#xff1a; 四、 帕累托分布 4.1 什么是幂律&#xff1f; 4.2 机器学习和数据科学中的帕累托分布示例…

怎么找抖音视频素材?在哪里找爆款热门的素材呢?

在短视频时代&#xff0c;拍摄和分享短视频已经成为一种潮流。但是&#xff0c;许多人都会面临一个问题&#xff0c;那就是——视频素材从哪里来&#xff1f;今天&#xff0c;我将为大家介绍几个优质的网站&#xff0c;让你的视频素材不再愁。 蛙学府&#xff1a;https://www.…

如何连接达梦数据库?

连接达梦数据库&#xff08;DM Database&#xff09;可以通过多种方式进行&#xff0c;包括使用 JDBC&#xff08;Java Database Connectivity&#xff09;驱动程序&#xff0c;这是最常见的方式之一。以下是使用 Java 通过 JDBC 连接达梦数据库的详细步骤&#xff1a; 1. 准备…

pve8群晖rr方式安装(编译失败检查网络或磁盘空间error 23:200问题解决)

PVE 篇二&#xff1a;2024年PVE8最新安装使用指南|安装黑群晖&#xff5c;img格式镜像安装_NAS存储_什么值得买 (smzdm.com) 黑群晖 篇五&#xff1a;2023黑群晖最新安装方式|RR新手也可轻松上手_NAS存储_什么值得买 (smzdm.com) 编译引导提示&#xff1a;检查网络或磁盘空间er…

Mybatis动态sql标签

动态SQL标签简介: MyBatis的一个强大的特性之一通常是它的动态SQL能力。如果你有使用JDBC或其他相似框架的经验,你就明白条件地串联SQL字符串在一起是多么的痛苦,确保不能忘了空格或在列表的最后省略逗号。动态SQL可以彻底处理这种痛苦。 Mybatis中实现动态sql的标签有&#x…

重生之 SpringBoot3 入门保姆级学习(24、场景整合 kafka 消息发送服务)

重生之 SpringBoot3 入门保姆级学习&#xff08;24、场景整合 kafka 消息发送服务&#xff09; 6.4 消息发送服务 6.4 消息发送服务 访问 kafka-ui &#xff08;注意这里需要换成你自己的服务器或者虚拟机的 IP 地址&#xff0c;虚拟机可以用局域网 192.168.xxx.xxx 的地址&…

AMD Lisa Su专访:谈与英伟达、Intel竞争 直言Arm不是敌人

AMD CEO Lisa Su&#xff08;苏姿丰&#xff09;绝对称得上是芯片届的风云人物&#xff0c;尤其是进入了AI新时代&#xff0c;她的声望达到了十年来最高点。翻看其成长历史&#xff0c;苏姿丰在麻省理工学院获得电气工程博士学位后&#xff08;在麻省理工学院学习八年半&#x…

sudo 用户切换

切换到centos 用户 sudo -i -u centos 解决centos sudo执行仍旧显示Permission denied 方法一&#xff08;建议&#xff09; 暂时切换到root用户 sudo -i然后执行命令即可 方法二 赋给当前用户权限&#xff1a; sudo chmod -R 777 目录路径 sudo chmod 777 文件路径.txt…

element--el-table合计换行显示

el-table合计换行显示 效果图实现1、使用到的参数2、代码演示 效果图 实现 1、使用到的参数 官网链接&#xff1a;element-table 将show-summary设置为true就会在表格尾部展示合计行。默认情况下&#xff0c;对于合计行&#xff0c;第一列不进行数据求合操作&#xff0c;而是…

浪潮信息MUPR自研专利 保障服务器内存运行的可靠性和高效性

在数字化转型的大潮中&#xff0c;服务器作为支撑企业业务运行的核心设备&#xff0c;其稳定性和可靠性显得尤为重要。然而&#xff0c;传统的内存故障预警修复技术往往存在反应滞后、误报率高等问题&#xff0c;难以满足日益增长的数据处理和存储需求。针对这一问题&#xff0…

用CloudCompare软件拟合点云中的圆柱体

用CloudCompare软件拟合点云中的圆柱体 软件下载 点击下面的链接&#xff0c;进入下载页面&#xff1a; 下载页面 然后根据需要选择下载合适的软件版本。 一般选择windows installer版&#xff0c;如图所示&#xff1a; 下载完成后&#xff0c;安装并打开软件。软件的默认语…

LC1020:飞地的数量

题目 给你一个大小为 m x n 的二进制矩阵 grid &#xff0c;其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相邻&#xff08;上、下、左、右&#xff09;的陆地单元格或跨过 grid 的边界。 返回网格中 无法 在任意次数的移动…