面试常考题:TOP-k问题(求很多数据最大或最小的前k个)三种方法以及适用场景。

使用背景

生活中,我们经常要给某些数据排序,比如美团上某一类型的外卖在一地区排名,拿我生活的地方举例,陕西排名前十的凉皮…。如果觉得不够亲切,拿王者荣耀来举例,陕西省最强李白,陕西省十强李白,陕西省百强李白。这时候,我们只能看到前一百名,后面的排名不重要,我们不需要给陕西所有的李白玩家都排名,用堆来解决再合适不过了。下面给出解决思路。
并且面试时,这个问题是一个常考题。

解决问题思路

思路1:直接排序

堆排序,冒泡排序,等等排序算法。
优点

  • 所有的数据都进行了排序,想要第多少名都可以。

缺点

  • 时间复杂度高,有时候我们并不需要全部排名,
  • 只要前十个数据等等

排序算法代码就不多赘述了,大家可以自己百度找找。

思路2:k次最值选择

(简化版的堆排序)
对所有数据建堆,堆顶即最值,建堆一次选出一个最值,取堆顶保存,对剩下的数据再建堆,算上第一次建堆,求k个数据,建k次堆,保存k个堆顶。
其他排序:k次冒泡,k次选择都可以。
优点

  • 较为优秀的解决办法,但有缺陷

缺点

  • 当数据量很大时,建堆内存不够怎么办?
  • 要取的数据多,k值很大建堆次数也上升。

代码:

思路3:堆替换

第一步: 求最小的前k个数,我们就建立一个含有k个数据的大堆(记住:求最小的建大堆,求最大的建立小堆)
第二步:然后将剩余的数据和这个堆的堆顶比较,如果小于堆顶,交换数据,向下调整入堆,直到所有数据比较完毕。

  • 解释1:这个堆的堆顶相当于一个门槛,这个堆顶是数据里第k小的,我们拿剩下的数据和这个门槛比较,比第k小还要小,自然就是我们要的值,入堆!
  • 解释2:这时又有疑问了,万一这个堆顶选出来就是最小的呢?那不是没有能进堆的?答案:笨蛋!我们建立的是大堆!大堆堆顶会是最小的嘛?

第三步:将这个k个数据的大堆进行堆排序,所得结果即为所求。

代码及检验

这个问题在leetcode上也有,给大家贴上链接:https 😕/leetcode-cn.com/problems/smallest-k-lcci

#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
void swap(int *a1, int *a2)
{
   
	int
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值