最近做面试题,经常与到一个问题,如何高效的从一组数中找到第K大的元素。

其实我们最容易想到的肯定是蛮力法。

1. 我们可以对这个乱序数组按照从大到小先行排序,然后取出前k大,总的时间复杂度为O(n*logn + k)。

2.选择排序和冒泡排序算法,即选择k次。(这种算法比较简单,这里就不介绍了)

3.利用快速排序改进。

利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
           1). Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
           2). Sa中元素的个数大于等于k,则返回Sa中的第k大数。时间复杂度近似为O(n)
但是在考虑快排的最坏情况,即每次快排只淘汰一个元素,时间复杂度为n*(n-1)*...*(n-k) 近似为O(n*k),但然这样的几率很小,我们可以通过随机选取划分元素,而不是固定选取首位元素作为划分元素来减小发生的概率。
 
4.用O(2*n)的方法对原数组建最大堆,然后pop出k次即可。时间复杂度为O(4*n + k*logn)
采用自底向上的构造法,最坏情况的时间复杂度为2(n-log(n+1)),所以构造堆的时间复杂度是线性的。
 
5.维护一个k大小的最小堆,对于数组中的每一个元素判断与堆顶的大小,若堆顶较大,则不管,否则,弹出堆顶,将当前值插入到堆中。时间复杂度O(n * logk)
 
6.利用hash保存数组中元素Si出现的次数,利用计数排序的思想,线性从大到小扫描过程中,前面有k-1个数则为第k大数,平均情况下时间复杂度O(n)
 
下面是第三种利用快拍改进的代码实现。
 //这个是快排代码
void QuickSort(int[] array, int begin, int end) {
if (begin >= end) {
return;
} int temp = array[begin];
int i = begin;
int j = end; while (i < j) { while (i < j && temp <= array[j]) {
j--;
}
array[i] = array[j]; while (i < j && temp >= array[i]) {
i++;
}
array[j] = array[i];
}
array[i] = temp; QuickSort(array, begin, i - 1);
QuickSort(array, i + 1, end);
}
 //这个是利用快拍改进后的代码

  int findK(int[] array, int begin, int end, int k) {
if (begin > end)
return -1; int temp = array[begin];
int i = begin;
int j = end; while (i < j) { while (i < j && temp >= array[j])
j--; array[i] = array[j]; while (i < j && temp <= array[i])
i++; array[j] = array[i];
}
array[i] = temp;
if (i == k - 1)
return array[i]; if (k - 1 < i)
return findK(array, begin, i - 1, k); return findK(array, i + 1, end, k);
}

从一组数找第K大元素的更多相关文章

  1. ACM_求第k大元素(两次二分)

    求第k大 Time Limit: 6000/3000ms (Java/Others) Problem Description: 给定两个数组A和B,大小为N,M,每次从两个数组各取一个数相乘放入数组C ...

  2. 快速排序算法的实现 && 随机生成区间里的数 && O(n)找第k小 && O(nlogk)找前k大

    思路:固定一个数,把这个数放到合法的位置,然后左边的数都是比它小,右边的数都是比它大 固定权值选的是第一个数,或者一个随机数 因为固定的是左端点,所以一开始需要在右端点开始,找一个小于权值的数,从左端 ...

  3. luogu_P1177 【模板】快速排序 (快排和找第k大的数)

    [算法] 选取pivot,然后每趟快排用双指针扫描(l,r)区间,交换左指针大于pivot的元素和右指针小于pivot的元素,将区间分成大于pivot和小于pivot的 [注意] 时间复杂度取决于pi ...

  4. 找第k大的数

    (找第k大的数) 给定一个长度为1,000,000的无序正整数序列,以及另一个数n(1<=n<=1000000),接下来以类似快速排序的方法找到序列中第n大的数(关于第n大的数:例如序列{ ...

  5. [LeetCode解题报告] 703. 数据流中的第K大元素

    题目描述 设计一个找到数据流中第K大元素的类(class).注意是排序后的第K大元素,不是第K个不同的元素. 你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包 ...

  6. 寻找无序数组中的前k大元素

    题目描述 以尽可能小的代价返回某无序系列中的两个最大值,当有重复的时设置某种机制进行选择. 题解 首先要考虑的是重复的数的问题. A.不处理重复数据方法:在处理第k大的元素时不处理重复的数据,也就是将 ...

  7. 【转载】两个排序数组的中位数 / 第K大元素(Median of Two Sorted Arrays)

    转自 http://blog.csdn.net/zxzxy1988/article/details/8587244 给定两个已经排序好的数组(可能为空),找到两者所有元素中第k大的元素.另外一种更加具 ...

  8. 第k大的数,前k大的数

    1.排序后去出前k个,o(n*log(n))    如果k<log(n),可以考虑直接选择排序,因为只需要执行找到第k个就可以结束 o(n*k) 2.o(nlog(k))快排把数分为了两个部分, ...

  9. 寻找两个已序数组中的第k大元素

    寻找两个已序数组中的第k大元素 1.问题描述 给定两个数组与,其大小分别为.,假定它们都是已按照增序排序的数组,我们用尽可能快的方法去求两个数组合并后第大的元素,其中,.例如,对于数组,.我们记第大的 ...

随机推荐

  1. Ubuntu下开启Mysql远程访问的方法

    首先想说,JetProfiler对分析项目中MySQL问题以及优化,是个非常好的工具.但是看网上文章,中文介绍真的不多.是因为国内现在都不用MySQL了吗? 因为公司JetProfiler是共用的,安 ...

  2. 进程池的同步与异步用法Pool

    进程池的同步,如下程序: from multiprocessing import Pool import time import os def func(n): print('start 进程 %s' ...

  3. Github Upload Large File 上传超大文件

    Github中单个文件的大小限制是100MB,为了能突破这个限制,我们需要使用Git Large File Storage这个工具,参见这个官方帖子,但是按照其给的步骤,博主未能成功上传超大文件,那么 ...

  4. nginx_ssl证书双向认证以及负载均衡配置

    #user nobody;worker_processes 1; #error_log logs/error.log;#error_log logs/error.log notice;#error_l ...

  5. js中 switch 注意事项

    var x = "2"; // 字符串 “2” switch (x) { case 1: console.log('x 等于1'); break; case 2: // 数值 2 ...

  6. 唉,可爱的小朋友---(DFS)

    唉,小朋友是比较麻烦的.在一个幼儿园里,老师要上一节游戏课,有N个小朋友要玩游戏,做游戏时要用小皮球,但是幼儿园里只有M个小皮球,而且有些小朋友不喜欢和一些小朋友在一起玩,而只喜欢和另一些小朋友一起玩 ...

  7. python全栈开发 * 36知识点汇总 * 180721

    36 操作系统的发展史 进程一.手工操作--穿孔卡片 1.内容: 程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把程序和数据输入计算机内存,接着通过控制 台开关启动程序针对 ...

  8. Spring Boot核心注解@SpringBootApplication

    一.作用   @SpringBootApplication是一个组合注解,用于快捷配置启动类. 二.用法   可配置多个启动类,但启动时需选择以哪个类作为启动类来启动项目. 三.拆解 1.拆解     ...

  9. -webkit-line-clamp、-webkit-box-orient vue 打包部署后不起作用??

    场景分析:实际开发中,文字描述过长,需要两行或三行显示缩略显示: 实现过程: 实现过程遇到的问题:打包到线上后发现并没有-webkit-box-orient属性,导致省略号并没有按预期展示: 解决方法 ...

  10. 关于什么是SpringMVC,和SpringMVC基于xml配置、注解配置、纯注解配置

    首先我们先要了解一下,什么是SpringMVC? SpringMVC是Spring框架内置的MVC的实现.SpringMVC就是一个Spring内置的MVC子框架,也就是说SpringMVC的相关包都 ...