求数组第K大的数

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

问题:有一个大小为n的数组A[0,1,2,…,n-1],求其中第k大的数。
我们先分析原问题:有一个大小为 n的数组A[0,1,2,…,n-1],求其中第k大的数。

我们先取特例,令k=1,那么就是取最大的数,只要扫描一遍数组就可以确定该值,如果k=2,则扫描两边数组就可以确定第二大的数,依此类推下去,时间复杂度是O(k*n),如果k跟n是一个数量级,那么时间复杂度就是O(n*n)了,显然不是最优的解法。

考虑分治法,难点在于如何将该问题分解为两个子问题。

快速排序最基础的一步:

   随机取某一个数x,将其与数组末尾元素交换,然后将比其小的数交换至前,比其大的数交换至后。

这一步使某一数组的快速排序问题分解成两个子数组的排序问题,现在我们就依此来解决取第k大的数这个问题。

设数组下表从0开始,至n-1结束。

1、 随机取某个数,将其与数组末尾元素交换。

a) idx=rand(0,n-1);生成[0,n-1]间的随机数。

b) Swap(array[idx], array[n-1]);

2、 用末尾元素x,将比x小的数交换至前,比x大的数交换至后,并返回此时x在数组中的位置mid。

3、 如果mid==n-k,那么返回该值,这就是第k大的数。

如果mid>n-k,那么第k大的数在左半数组,且在左半数组中是第k-(n-mid)大的数。

如果mid

#include "iostream"  
using namespace std;  

int random_partion(int *p, int n)  
{  
     int idx=rand()%n;  
     swap(p[idx], p[n-1]);  
     int i=-1;    //i表示最后一个小于p[n-1]的元素的位置  
     int j=0;     //j用来扫描数组  
     for(j=0; j<n; j++)  
     {  
            //将小于p[n-1]的数交换到前半部分  
            if(p[j]<p[n-1])  
            {  
                swap(p[++i], p[j]);  
            }  
     }  
     swap(p[++i], p[n-1]);  
     return i;   
}  

int getMaxK(int *p, int n, int k)  
{  
    int mid;  
     if(k<=0)  
            return -1;  
     if(n<k)  
            return -1;  
     mid=random_partion(p, n);   //对原数组进行一次划分  
     if(mid == n-k)      //如果mid==n-k,那么返回该值,这就是第k大的数  
         return p[mid];  
     else if(mid<n-k)  
         return getMaxK(p+mid+1, n-mid-1, k);  //如果mid<n-k,那么第k大的数在右半数组,而且仍然是第k大数  
     else  
         return getMaxK(p, mid, k-(n-mid));   //如果mid>n-k,那么第k大的数在左半数组,且在左半数组中是第k-(n-mid)大的数  
}  

int main(void)  
{  
    int num,a[] = {12012, 3, 945, 965, 66, 232, 65, 7, 8, 898, 56, 878, 170, 13, 5};  
    num=getMaxK(a, 15, 4);  
    printf("%d\n",num);  
    system("pause");  
    return 0;  
}  
M1/M2 Mac用户看过来:不装VirtualBox,用PD虚拟机也能跑ENSP的保姆级教程 本文为M1/M2 Mac用户提供了一份不依赖VirtualBox,使用Parallels Desktop虚拟机运行ENSP的详细指南。通过ARM架构的Win10镜像选择、组件替代方案和网络配置优化,实现ENSP核心功能的高效运行,特别适合网络工程师在苹果芯片设备上进行网络模拟。 阅读详情

相关推荐

【AI模型应用开发实战】型语言模型评估指南白皮书(LLM Eval)

近年来,型语言模型(LLM)在自然语言处理领域取得了重进展,例如 GPT-3 和 Chat-GPT。这些模型经过据集的训练,在文本相关任务中表现出卓越的能力,甚至超越了人类。本文将简要介绍如何验证 LLMs 性能的评估指标。自然语言处理(NLP)是人工智能的一个领域,涉及计算机和人类语言之间的交互。NLP 的基本任务之一是语言建模 (LM),它涉及构建统计模型来分析和生成自然语言。LM 已成为推进机器语言智能的关键方法,使机器能够执行机器翻译、情感分析和对话系统等任务。

AI天才研究院 968

数组中第k个最(TopK)三种解法

TOPK、三种解法、快排、堆排、二分

Z_CAIGOU的博客 2151

光伏微电网蓄电池储能控制系统设计及动态性能分析

本文构建了光伏微电网蓄电池储能控制系统的完整理论体系。在系统架构方面,提出了基于直流母线电压平衡的多时间尺度能量管理理论,建立了光伏发电单元的二阶物理模型和MPPT动态跟踪算法。针对蓄电池系统,设计了融合二阶RC等效电路与扩展卡尔曼滤波的SOC估计方法,误差控制在3%以内。双向DC-DC变换器采用状态空间平均建模方法,推导了小信号传递函,为闭环控制提供理论基础。该体系实现了从瞬时功率平衡到长期能量调度的多层级协同控制,为微电网稳定运行提供了系统的解决方案。

AI的内部世界的博客 167

快速排序——寻找数组第K(由浅入深,四种方法对比讲解!)

寻找数组第K厂面试中经常考到的一题,有的小机灵鬼直接用sort()进行排序,两行代码解决,这样看似可行,实则掉入了出题人的陷阱!

不积跬步,无以至千里! 2万+

寻找数组中第k

题目:有一个整数组,请你根据快速排序的思路,找出数组中第K。 给定一个整数组a,同时给定它的小n和要找的K(K在1到n之间),请返回第K,保证答案存在。 测试样例: [1,3,5,2,2],5,3 返回: 2 方法一: 利用冒泡排序,进行k趟排序,即可查找到第k(每趟冒泡排序都寻找当前序列中的最大值) 方法二: 利用选择排序,进行k趟排序,即可查找到第k(每趟选择排序都寻找当前序列中的最大值) 方法三: 利用快速排序的思想,只需找到第k,不必把所.

m0_37671741的博客 7918

Leetcode215 寻找数组中第K

剑指offer——寻找数组中的第 K 题目描述 给定一个数组A,要找到数组A中第K字。 思路:对于这种题目,其实有多种解法 方法1:对数组A进行排序,然后遍历一遍就可以找到第K字。该方法的时间复杂度为O(N*logN) 方法2:利用简单选择排序法的思想,每次通过比较选出最字来,比较上K次就能找出第K字来。该方法的时间复杂度为O(N*K),最坏情况下为O(N^2)。 方法3:也是本文介绍的最重要的一种方法。利用快速排序算法 partition 的思想来解决。首先快

neverSaynever_的博客 5297

寻找第(前)k的方法总结

问题描述 给定一个包含n个的乱序数组,寻找其中第k。 方法总结 解法1:先将乱序数组按照从到小排序,然后取出第k。时间复杂度为O(n*logn)。 解法2:利用选择排序,k次选择后即可得到第k。时间复杂度为O(n*k)。 解法3:利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素于等于X,Sb中元素小于X。这时有两种

Enjoy Coding 2595

数组中第K

本题的的数组是可以包含重复元素的,且要时间复杂度控制在O(n) 解题思路:数组中第k等价于排序数组中第n-k个,直观的想法是将数组排序后取第n-k个即可,但是最快的排序算法时间复杂度也是O(logn), 可以参考快速排序一次划分的思想,将时间复杂度降低为O(n);一次划分可以讲数组分为三部分,比支点元素小或者与支点元素相等的部分,支点元素,比支点元素的部分。一次partition之后

Logan的博客 3382

无序数组的第K(/小)的三种方法

题目描述:给定一个无序数组(长度为n)和一个正整 K,让你数组中第K 方法1:最简单的思路,你肯定会想到 先把数组排序,然后再取下标为K的对应数组元素。这种方法肯定是可行的,但是这种方法无端的对咱们不需要查找的元素也进行了处理,在一定程度上增加了算法的消耗!这样是不值得的!此方法的平均时间复杂度为O(n*logn). 方法2:利用堆调整算法的性质,建立一个小为K的堆,然后将整个...

liuwq012的专栏 8776

无序数组第 K

规定,第一维据从小到,第一维据一样的,第二维数组也从小到。一组,不足一组的补齐一组,并对每组进行排序(由于固定是5个一组进行排序,所以排序的时间复杂度。),取出每组的中位,组成一个新的数组, 对新的数组其中位,这个中位就是我们需要的值。的过程, 这个过程随机选择数组中的一个,假设叫pivot,这个过程主要作用是将数组的。,接下来的元素继续入堆,但是每入一个就弹出一个,最后,堆顶元素就是整个数组的第。返回两个值,一个是左边界和一个右边界,位于左边界和右边界的值均等于。

Practitioner 2256

一个数组中前K或者第K

#include using namespace std; void BubbleSort(int a[], int alen) { for(int i = 0; i < alen; i++) { for(int j = alen-1; j > i; j--) { if(a[j] > a[j-1])

紫天火雨 3135

无序数组的第K

1、利用快排的思想,只在满足要的片段上进行排序,解,这样时间复杂度由O(nlogn)变为O(n)。 按从到小的进行排序,将的都放在左边,经过第一次迭代划分结束后,枢轴的位置左侧均比枢轴原始,如果枢轴的位置first刚好等于k-1(数组下标从0开始计),则枢轴元素即为第k,如果first比k-1,说明第k的元素在左侧,这样只排左侧就可以,右侧抛弃;如果枢轴位置first...

zcc_0015的专栏 276

C++实现数组中前K

C++实现数组中前K

坚持 2345

java无序数组中第k

无序数组中第k 最近工作不是很紧,闲下来学习巩固一下,看到一道面试题,解一下,main方法运行成功, public static void main(String[] args) { int[] a = {62,35,3,78}; int k = 2; int num = 0; for(int i = 0; i<a.length;i++){ if(a[i]>a[k]) { ...

weixin_44859876的博客 858

无序数组中第k

如果是排好序的数组,则比较简单,直接$arr[$k-1]就能出,如果不是排好序的就需要先排序,但这种时间复杂度为O(n2),所以不能直接排序。我们知道快速排序就是找一个哨兵,使左边的比它,右边的比它小,然后在对左右两边的重复上次的动作。可以利用快速排序中的步骤,找的哨兵,在排完一步的序后,如果等于$k,则这个位置就是要找的,如果小于哨兵的位置,则重新对哨兵左边的进行排序就好,没必要在对...

Mr.yang 2583

无序数组第k python_整无序数组第K

import java.util.Scanner;/*** 类似与第k小的问题* 第k相当于第n-k+1小,n为数组长度** 著名的BFPRT算法可保证在线性时间内得到结果。* https://blog.csdn.net/qq_32767041/article/details/86099117** 这里使用快速选择算法,这是一种基于快速排序的算法,* 在实现上比BFPRT更简单。* htt...

weixin_39960503的博客 265

java数组中第K

这是我在面试中面试官问过我的一个问题,网上也有很多人说遇到过这样的问题,说实话这个题很操蛋也很经典,选对方法才是关键。 public static void main(String[] args) { //数组中第K int [] n={1,23,12,12,12,58,24,44,32,56,56,56,67,23,44}; repe...

jeesp企业框架 495

N个数组中第K的值

方法一:将这N个数组,通过简单的冒泡排序法,以递减的顺序将数组排序,然后返回第K个元素。 方法二:先把前K个元素拷贝到数组b,以递减的顺序对其排序,然后,将剩下的元素逐个与数组b比较, 如果小于数组b中的第K个元素则忽略,否则将新元素放到数组b中正确的位置上,同时将数组b中的一个 元素挤出数组。当算法终止时,返回数组b中第K个元素。 代码实现: 1 #defin...

allen2111的博客 1002

一个数组的第K

一个数组的第K

-lim-的博客 824

两个有序数组的第k

题目:给定两个一维int数组A和B. 其中:A是长度为m、元素从小到排好序的有序数组。B是长度为n、元素从小到排好序的有序数组。希望从A和B数组中,找出最的k个字,要:使用尽量少的比较次。 解法: 1.首先介绍上中位的概念(算法原型) 在编写判断上中位的函时,首先要保证两个数组的长度相同。 1.1 当两个数组长度均为偶时 eg:arr1 = {a,b,c,d}; arr2 = {e,f,g,h},第4 当 b==f 时,有 b,f均为上中位 ...

m0_58466443的博客 825
上一篇: 注释转换
下一篇: 课程设计---图书登记管理系统
cy320h
博客等级 码龄9年 46粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值