起因:2020.11.19 网易互娱面试

面试官:如果有一个战力排行榜,需要实时显示前K名的玩家,你会怎么操作?

我:直接使用最小堆,Java中有priority queue,把它的大小设置为K,每次将数据与它最小的元素(即priorityQueue.peek())比较,比它大就入队,priorityQueue.size()大于k了就弹出peek。这样时间复杂度是

面试官:你能再优化一下吗?

topK问题的一步步优化详解:

->
->
->

给定一个数组nums[],怎样能输出前K大的所有数字呢?

e.g. int[] nums = {8,7,6,5,4,3,2,1}; int k = 3, output: 8, 7, 6

solution 1:直接排序

将nums[]直接进行快排/归并/冒泡等排序,时间复杂度为

.

简单粗暴,将所有元素排序,但也很明显地增加了工作量,在面试中是很没营养的说法,说了等于没说。

solution 2:局部冒泡

首先厘清一下冒泡排序的逻辑:

public 

每次遍历都可以找到一个最大/最小的元素,那么遍历k次就可以找出topK,时间复杂度为

,代码如下:
public 

solution 3:最小堆/优先队列

什么是最小堆?

堆是一种基本的数据结构,在最小堆中,它的任意一个顶点的值都不大于其子节点。即根节点是该堆中值最小的元素。

最小堆是一棵树,我们很容易得出拥有n个节点的最小堆插入新数据并进行比较的时间复杂度为

我们只需要遍历一次数组。由于最小堆的首节点一定是堆中的最小值,所以如果遍历到的数字大于最小堆的根节点,就弹出首节点,并压入该数字。

Java中的priority queue是一个已经实现的最小堆,很方便,当然手冲堆排序也可以,不过没必要。

直接上代码:

public 

其思路与局部冒泡法不同的是,局部冒泡在每次遍历后都能找到一个最大的值,而最小堆法维护了一个“已遍历数据中最大的K个值”的数据结构。

时间复杂度分析非常简单,遍历一次数组是n,由于最小堆的大小是k,所以每次对最小堆操作是logk,所以该算法的时间复杂度为

我们只需要在服务器维护时间建立好我们的小根堆,在游戏服务器开服的时候,如果有玩家氪金导致战斗力变化,我们可以直接将该数据与堆的根节点比较,从而很方便地维护排行榜。

前三种方法都比较好理解,也是基本的方法。

solution 4:分治

此种方法来自于一名知友的回答:

https://zhuanlan.zhihu.com/p/89229902​zhuanlan.zhihu.com

其算法的思路大致如下:

在合并数组的时候,维护一个大小为k的空间,内容为该次合并后最大的K个数。

算法过程是很好理解的,但是原作者在回答中说,该算法的时间复杂度为

,应当是有纰漏的。

倘若时间复杂度为

,首先对n个元素的数组进行分治和合并就无法在
内完成。

可以肯定的是,该算法的时间复杂度应该是优于直接排序法的,但同时它也带来了额外的空间消耗,因为它至少为每个元素都申请了一个大小为k的数组。

solution 5:线性时间复杂度的搜索算法

思维逐渐深入,既然我要找topK,那我是不是能通过先寻找第K大的数,再用数组里的所有数据与它比较呢?

这种方法是一定可行的,并且它拥有很优秀的时间复杂度。

首先,一句话说明快速排序的逻辑:随机挑选一个pivot,在进行一次算法后,pivot左边的数字都小于它,右边的数字都大于它,换句话说,通过计算最后pivot的下标,就能计算出它是原数组中第几大的数

怎么修改数组中指定元素_topK问题总结:数组中的前K大元素相关推荐

  1. python列表元素求和_对Python列表的前k个元素求和?

    有两个选项,都使用sum():使用^{}可以有效地提取这些元素:from itertools import islice sum(islice(somelist, k)) 将列表切片,以便只包含以下第 ...

  2. 数组中的元素赋值给元素_漫画:寻找无序数组的第k大元素

    本期封面作者:泰勒太乐 -----  第二天  ----- 题目是什么意思呢?比如给定的无序数组如下: 如果 k=6,也就是要寻找第6大的元素,这个元素是哪一个呢? 显然,数组中第一大的元素是24,第 ...

  3. 如何寻找无序数组中的第K大元素?

    如何寻找无序数组中的第K大元素? 有这样一个算法题:有一个无序数组,要求找出数组中的第K大元素.比如给定的无序数组如下所示: 如果k=6,也就是要寻找第6大的元素,很显然,数组中第一大元素是24,第二 ...

  4. 网易_在数组中查找前K个元素

    笔试题,最后一题 查找网易云音乐中播放量最大的前K个歌曲. 换句话说,就是在数组中查找前K大元素. 大致有以下几个思路. 1.第一感觉就是对数组进行降序全排序,然后返回前K个元素,即是需要的K个最大数 ...

  5. 数组中第K大元素(java多种方式实现)

    题目描述: Leetcode215题:在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5 ...

  6. 在一个无序的int数组上构建一个最小堆的时间复杂度_漫画:寻找无序数组的第k大元素(修订版)...

    ----- 第二天 ----- 题目是什么意思呢?比如给定的无序数组如下: 如果 k=6,也就是要寻找第6大的元素,这个元素是哪一个呢? 显然,数组中第一大的元素是24,第二大的元素是20,第三大的元 ...

  7. 从当前元素继续寻找_云漫圈 | 寻找无序数组的第k大元素

    戳蓝字"CSDN云计算"关注我们哦! 作者:小灰 来源:程序员小灰 本期封面作者:泰勒太乐 -----  第二天  ----- 题目是什么意思呢?比如给定的无序数组如下: 如果 k ...

  8. 云漫圈 | 寻找无序数组的第k大元素

    戳蓝字"CSDN云计算"关注我们哦! 作者:小灰 来源:程序员小灰 本期封面作者:泰勒太乐 -----  第二天  ----- 题目是什么意思呢?比如给定的无序数组如下: 如果 k ...

  9. 遍历数组是什么意思_漫画:寻找无序数组的第k大元素(修订版)

    ----- 第二天 ----- 题目是什么意思呢?比如给定的无序数组如下: 如果 k=6,也就是要寻找第6大的元素,这个元素是哪一个呢? 显然,数组中第一大的元素是24,第二大的元素是20,第三大的元 ...

  10. 第k大元素(时间复杂度为O(n))

    2201: 第k大元素 [命题人 : yancheng] 时间限制 : 1.000 sec  内存限制 : 128 MB 提交 解决: 156提交量: 1038统计 题目描述 输入一个整数数组,请求出 ...

最新文章

  1. 数据库1.0 -- 数据库的基本操作
  2. AlphaCode能替代人类程序员吗?网友:被替代也挺好,这样就可以少写代码多开会了...
  3. Windows 2003 系统应用故障的分析
  4. Winform DataGridView列的单元格中动态添加图片和文字
  5. putty-psftp
  6. 死磕Java并发:深入分析volatile的实现原理
  7. python查看文件夹下所有文件
  8. Java 如何优雅的实现时间控制
  9. mysql操作日志记录查询_详解mysql数据库参数log_timestamps--控制日志记录使用的时区...
  10. 会议邀请 | 中国中文信息学会暑期学校《前沿技术讲习班》
  11. matplotlib库绘图基础
  12. TypeScript--泛型
  13. 浅谈导航电子地图的组成和制作流程
  14. php date 有warning,php提示PHP Warning: date(): It is not safe to rely on the......错误的解决办法...
  15. c语言实现线程相关操作,如何用C语言实现多线程
  16. mysql字段加密存储过程_数据库:加密存储过程
  17. 机顶盒系统升级服务器地址,tvbox
  18. 清华大学计算机研究生课程表
  19. 联想拯救者u盘安装linux系统,联想拯救者Y7000系统盘重装如何设置U盘启动
  20. 计算机禁用打印驱动服务器,设备: 防止用户安装打印机驱动程序

热门文章

  1. bootstrap-validation 对表单进行比较全的验证
  2. 最普通IT男-苦逼coder杂谈
  3. 基于linux的安全通讯过程
  4. 新建SVN Repository
  5. 第一节:Create React App
  6. dynamic集合动态添加属性
  7. 如何验证 nginx.conf 是否配置正确
  8. linux平台上不同类型的压缩文件的压缩与解压
  9. 六石管理学:切勿通过扯皮折腾别人,一句你不要管了即可
  10. ldconfig清理缓存