求 Top K 的算法主要有基于快速排序的和基于堆的这两种,它们的时间复杂度都为 \(O(nlogK)\)。借助于分治思想,以及快速排序的区间划分,我们可以做到 \(O(n)\) 时间复杂度。具体算法思路如下:

  • 第 1 步,我们将原数据 5 个一组划分为若干个组,最后余下的不足 5 个的额外作为一组,总组数为 \(g=\lceil{n/5}\rceil\);
  • 第 2,3 步, 对每一个组内的 5 个元素利用插入排序算法进行排序,然后将每个组的中位数依次放到数据的前面,最后 \(A[0, g-1]\) 保存的便是 \(g\) 个组各自的中位数;
  • 第 4 步,递归调用求出 \(A[0, g-1]\) 的中位数,也即是元素 \(A[g/2]\),不知是否可以直接得到;
  • 第 5 步,以上一步得到的中位数对数据划分区间,左边小于中位数,右边大于中位数,中位数位于第 \(k\) 个位置;
  • 第 6 步,如果我们要找的正好是第 \(k\) 大数,那么刚刚得到的中位数即为所求;
  • 第 7 步,如果 \(i<k\) 我们要找的第 \(i\) 大数位于区间 \(A[0, k-1]\),在左半边递归求取第 \(i\) 大的数;
  • 第 8 步,如果 \(i>k\) 我们要找的第 \(i\) 大数位于区间 \(A[k+1:-1]\),在右半边递归求取第 \(i-k\) 大的数。
def insert_sort(data, left, right):

    # 对列表 data[left, right] 进行插入排序

    for i in range(left+1, right+1):
num = data[i]
for j in range(i, left, -1):
if num < data[j-1]:
data[j] = data[j-1]
else:
break
data[j] = num def swap(data, i, j): # 交换列表 data 位于 i,j 的元素 temp = data[i]
data[i] = data[j]
data[j] = temp def partition(data, x): # 按照列表 data 第 x 个元素分区 n = len(data)
i = 0
pivot = data[x]
swap(data, x, n-1)
for j in range(0, n):
if data[j] < pivot:
swap(data, i, j)
i += 1 data[j] = data[i]
data[i] = pivot return i def select_ith_min(data, i): # 选取列表 data 中第 i 小的元素 n = len(data) # 不要忘了递归终止
if n == 1:
return data[0] if n % 5 == 0:
group = n // 5
else:
group = n // 5 + 1
for j in range(0, group):
start = j * 5
end = start + 4
if end > n - 1:
end = n - 1
insert_sort(data, start, end)
mid = (end - start + 1) // 2 + start
swap(data, j, mid) pivot = data[group // 2]
k = partition(data, group // 2) if k == i-1:
return pivot
elif k > i-1:
return select_ith_max(data[0:k], i)
else:
return select_ith_max(data[k:], i-k) a = [i for i in range(100, 0, -1)]
print(a)
for i in range(1, 101):
num = select_ith_max(a, i)
print(num)

获取更多精彩,请关注「seniusen」!

线性时间求取第 K 大数的更多相关文章

  1. POJ 2104 K-th Number ( 求取区间 K 大值 || 主席树 || 离线线段树)

    题意 : 给出一个含有 N 个数的序列,然后有 M 次问询,每次问询包含 ( L, R, K ) 要求你给出 L 到 R 这个区间的第 K 大是几 分析 : 求取区间 K 大值是个经典的问题,可以使用 ...

  2. [csu/coj 1080]划分树求区间前k大数和

    题意:从某个区间内最多选择k个数,使得和最大 思路:首先题目给定的数有负数,如果区间前k大出现负数,那么负数不选和更大,于是对于所有最优选择,负数不会出现,所以用0取代负数,问题便转化为区间的前k大数 ...

  3. 算法导论学习之线性时间求第k小元素+堆思想求前k大元素

    对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思 ...

  4. [hdu3949]XOR(线性基求xor第k小)

    题目大意:求xor所有值的第k小,线性基模板题. #include<cstdio> #include<cstring> #include<algorithm> #i ...

  5. 线性时间O(n)内求数组中第k大小的数

    --本文为博主原创,转载请注明出处 因为最近做的WSN(wireless sensor network)实验要求用3个传感器节点接受2000个包的数据并算出一些统计量,其中就有算出中位数这么一个要求, ...

  6. 线性基求第k小异或值

    题目链接 题意:给由 n 个数组成的一个可重集 S,每次给定一个数 k,求一个集合 \(T \subseteq S\), 使得集合 T 在 S 的所有非空子集的不同的异或和中, 其异或和 \(T_1 ...

  7. O(n)线性时间找第K大,中位数

    运用快速排序的思想,可以达到线性时间找到一串数的第K大 #include<cstdio> #define F(i,a,b) for(int i=a;i<=b;i++) ],n; vo ...

  8. K:求取数组中最大连续子序列和的四个算法

    相关介绍:  求取数组中最大连续子序列和问题,是一个较为"古老"的一个问题.该问题的描述为,给定一个整型数组(当然浮点型也是可以的啦),求取其下标连续的子序列,且其和为该数组的所有 ...

  9. HDU - 3949 :XOR(线性基,所有集合的不同异或和中,求从小到大第K个)

    XOR is a kind of bit operator, we define that as follow: for two binary base number A and B, let C=A ...

随机推荐

  1. HTTP 缓存简单了解

    HTTP 缓存简单了解.文章整理了相关资料,记录了部分实践.方便大家轻松了解缓存.能回答上三个问题,HTTP缓存就算理解呢.能否缓存?缓存是否过期?协商缓存? 概要: web缓存 缓存的处理 前端解决 ...

  2. 关于mysql的查询优化

    由于工作原因,最近甲方客户那边多次反应了他们那边的系统查询速度慢,经过排除之后,发现他们那边的数据库完全没有用到索引,简直坑得一笔,通过慢查询日志分析,为数据表建立了适当的索引之后,查询速度明显的提高 ...

  3. IMAPd - Internet 邮件存取协议服务器

    总览 /usr/etc/imapd 描述 imapd 是个支持 IMAP4rev1 远程邮件存取协议(由RFC2060定义)的服务器. imapd 是由internet服务器(参见 inetd(8)) ...

  4. DigitalOcean 推荐的ubuntu16下LAMP安装过程

    LAMP安装过程: How To Install Linux, Apache, MySQL, PHP (LAMP) stack on Ubuntu 16.04 (另一个参考例程:Ubuntu 16.0 ...

  5. 021-Zabbix4.2对IIS监控摸索记录

    Zabbix是很强大,但是相关的细节技术文档貌似很少,摸索之路就显得异常难. 度娘搜了下,关于Zabbix对IIS的监控资料确实有,确实也讲如何操作了,但是细细按照对方的要求操作下,总是缺数据,no ...

  6. zencart产品批量采集伪原创方法,再也不用担心与别人的数据重复了

    首先,请你提供与产品相关的关键词一份,至于关键词如何来,相信做SEO的你很清楚了,SEO关键词搜索工具应该很多,比如谷歌相关关键词搜索,用记事本的形式保存为每行一个关键词.采集产品的时候,我会帮你将关 ...

  7. 十三、S3C2440 裸机 — 初始化代码及MMU

    13.1 NOR FLASH 搬运 把程序从 nor flash 上搬运到 SDRAM 中 程序存储在 nor flash 上,运行时将程序搬运到 SDRAM 中运行 nor flash 启动:nor ...

  8. canal 环境搭建 kafka Zookeeper安装(二)

    第一步 创建Zookeeper 下载完成后 修改 Zookeeper中的 zoo.cfg 修改 dataDir .dataLogDir 集群模式 server.1=ServerIP:2888:3888 ...

  9. 牛客挑战赛34 A~E

    闷声发大财 A O(nmk)dp即可,因为带了1/2的常数+2s所以很稳 #include <algorithm> #include <iostream> #include & ...

  10. python 面向对象_2

    self的理解 通俗理解self就是实例对象,实例化的是什么,self就是什么 实例变量: 经过实例化才能使用的变量 class Person(): def __init__(self,id,name ...