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

news2024/11/25 0:33:59

题目地址

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,一部分大于等于e
    while (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_index
    int len_S1 = right - e_index;
    // 如果S1长度大于k
    if (len_S1 >= k)
    {
        //S1和S2都不包括基准数e
        return 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_index
    int len_S1 = 0; //先初始化为0
    while(left <= right)
    {
        e_index = divide(nums, left, right);
        len_S1 = right - e_index;
        // 如果S1长度大于k
        if (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,一部分大于等于e
    while (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_index
    int len_S1 = right - e_index;
    // 如果S1长度大于k
    if (len_S1 >= k)
    {
        //S1和S2都不包括基准数e
        return 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_index
    int len_S1 = 0; //先初始化为0
    while(left <= right)
    {
        e_index = divide(nums, left, right);
        len_S1 = right - e_index;
        // 如果S1长度大于k
        if (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.coloradmin.cn/o/1827837.html

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

相关文章

C++ string字符串的使用和简单模拟实现

目录 前言 1. string简介 2. string的使用和简单模拟实现 2.1 string类的定义 2.2 string(),~string()和c_str() 2.2 size&#xff0c;重载符号[ ]&#xff0c;begin和end函数 2.3 push_back&#xff0c;reserve&#xff0c;append&#xff0c;运算符重载 2.4 insert和…

记录AE快捷键(持续补充中。。。)

记录AE快捷键 快捷键常用快捷键图层快捷键工具栏图层与属性常用指令视图菜单时间轴常规快捷键项目首选项功能摄像机操作 常用操作导入AI/PS工程文件加选一个关键参数快速回到上下一帧隐藏/显示图层关键帧拉长缩短关键帧按着鼠标左键不松手&#xff0c;在秒表那一列往下移动会都…

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

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

重生奇迹MU圣导师简介

出生地&#xff1a;勇者大陆 性 别&#xff1a;男 擅 长&#xff1a;统率&宠物使用 转 职&#xff1a;祭师&#xff08;3转&#xff09; 介 绍&#xff1a;当玩家账号中有一个Lv250以上角色时&#xff0c;便可以创建职业为圣导师的新角色&#xff0c;圣导师每升一级获得…

经典电源电路基础(变压-整流-滤波-稳压)

1.电源电路的功能和组成 电子电路中的电源一般是低压直流电&#xff0c;先把220v交流电变换成低压直流电&#xff0c;再用整流电路变成脉动的直流电&#xff0c;最后用滤波电路滤除掉脉动直流中的交流成分后才能得到直流电。有的电子设备对电源的质量要求很高&#xff0c;所以…

MQTTfx连接阿里云(详细版)

1、介绍 作为物联网开放平台&#xff0c;阿里云可谓是吸引大多数嵌入式爱好者的平台。物联网MQTT协议火热的今天&#xff0c;你使用过阿里云吗&#xff1f;本篇文章带你接触阿里云&#xff0c;实现MQTT通信。 我们在测试MQTT之前先了解下什么是MQTT协议。大家都知道它是一种发…

【2024最新精简版】SpringBoot面试篇

文章目录 Spring和SpringBoot的区别 ?讲一讲SpringBoot自动装配的原理&#x1f44d;讲一讲SpringBoot启动流程你们常用的Starter有哪些&#x1f44d;如何定义一个SpringBoot的starter &#x1f44d;SpringBoot支持的配置文件有哪些&#x1f44d;讲一讲SpringBoot项目配置文件的…

用Python比较对象==与is,你还在用==?out啦,来看这个!

目录 1、基础比较:== 和 is 📐 1.1 ==:值的比较 1.2 id()函数揭秘对象身份 1.3 is:身份的辨识 1.4 实战演练:列表、字典的比较陷阱 列表比较陷阱 2、深入理解比较操作符 🌀 2.1 不等号的妙用 2.2 成员资格in操作 3、自定义比较:__eq__等魔法方法 🎩 3.1 重…

蓝队-溯源技巧

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

1586. 扫地机器人

问题描述 Mike同学在为扫地机器人设计一个在矩形区域中行走的算法,Mike是这样设计的:先把机器人放在出发点 (1,1)(1,1) 点上,机器人在每个点上都会沿用如下的规则来判断下一个该去的点是哪里。规则:优先向右,如果向右不能走(比如:右侧出了矩形或者右侧扫过了)则尝试向…

分布式数据库核心问题和解决方法

当下&#xff0c;由于成本压力以及数据保护的要求&#xff0c;采用国产数据库的呼声越来越高&#xff0c;但是国产数据库数量众多&#xff0c;良莠不齐&#xff0c;没有选择数据库比较靠谱的标准&#xff0c;业内真正懂得数据库的人很少&#xff0c;且为了这块大的蛋糕&#xf…

《C语言深度解剖》(19):从头开始全面理解C语言指针和数组

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《C语言深度解剖》《精通C指针》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多C语言深度解剖点击专栏…

实例详解C/C++中static与extern关键字的使用

目录 1、概述 2、编译C++代码时遇到的变量及函数重复定义的问题 3、用 extern 声明外部变量 4、extern与全局函数 5、为何在变量和函数前添加一个static关键字编译就没问题了呢? 6、静态局部变量 7、函数的声明与定义都放置到一个头文件中,不使用static,通过宏控制去…

广东启动“粤企质量提升工作会议” 着力提升产品和服务质量

6月5日,由广东质量峰会组委会牵头,联合相关质量、信用、打假和检验检测等部门共同举办的“粤企质量提升工作会议”在广州正式启动。本次工作会议旨在贯彻落实《质量强国建设纲要》及《广东省质量强省建设纲要》精神,深入开展全民质量行动,弘扬企业家和工匠精神,营造政府重视质量…

实战17:GCN+LSTM图卷积神经网络预警预测 完整代码数据集

直接看视频演示: GCN+LSTM图卷积神经网络预警预测时间序列预测_哔哩哔哩_bilibili 模型图原理: 完整代码: import torch import torch.nn as nn import torch.optim as optim from torch_geometric.nn import GCNConv from torch.utils.data import DataLoader, TensorDat…

十二星座女、具有哪些情感特质。

白羊座&#xff08;奋不顾身&#xff09;。金牛座&#xff08;爱财如命&#xff09;。双子座&#xff08;灵活多变&#xff09;。 巨蟹座&#xff08;似水柔情&#xff09;。狮子座&#xff08;光明磊落&#xff09;。处女座&#xff08;尽善尽美&#xff09;。 天秤座&#xf…

【Unity学习笔记】第十八 基于物理引擎的日月地系统简单实现

转载请注明出处: https://blog.csdn.net/weixin_44013533/article/details/139701843 作者&#xff1a;CSDN|Ringleader| 目录 目标数学理论资源准备数据准备代码实现Unity准备效果展示注意事项后记 目标 目标&#xff1a;利用Unity的物理引擎实现 “日地月三体系统” 。 效果…

CubeMX Keil Configure

// 使用外部高速晶振 外部高速晶振为8M&#xff08;根据开发板上的晶振频率设置&#xff09;&#xff0c;使用 PLLCLK&#xff0c;HSE 选项 USART1 使用 Asynchronous&#xff0c;PA9&#xff0c;PA10引脚&#xff08;USART1 引脚根据开发板上引脚设置&#xff09; 设置MDK AR…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] URL拼接(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 URL拼接(100分) 🌍 评测功能需要订阅专栏后私信联系清隆解…

Pixel Transformer:用像素代替补丁可以提升图像分类精度

在快速发展的人工智能领域&#xff0c;ViTs已成为各种计算机视觉任务的基础模型。ViTs通过将图像划分为小块并将这些小块作为标记来处理图像。6月刚发布一篇论文&#xff0c;引入了一种新颖的方法&#xff0c;即像素级Transformers&#xff0c;它通过将单个像素视为令牌来挑战这…