Top K问题

1、全部直接排序
排序是最容易想到的方法,将n个数排序之后,取出最大的k个,即为所得。
伪代码:
sort(arr, 1, n);
return arr[1, k];
时间复杂度:O(n*lg(n))
分析:明明只需要TopK,却将全局都排序了,这也是这个方法复杂度非常高的原因。那能不能不全局排序,而只局部排序呢?
这就引出了第二个优化方法。

2、快速排序
局部排序
不再全局排序,只对最大的k个排序。冒泡是一个很常见的排序方法,每冒一个泡,找出最大值,冒k个泡,就得到TopK。
伪代码:

for(i=1 to k){
    bubble_find_max(arr,i);
}

return arr[1, k];
时间复杂度:O(n*k)

3、最小堆法
先用前k个元素生成一个小顶堆,
这个小顶堆用于存储,当前最大的k个元素。
接着,从第k+1个元素开始扫描,和堆顶(堆中最小的元素)比较,如果被扫描的元素大于堆顶,则替换堆顶的元素,并调整堆,
以保证堆内的k个元素,总是当前最大的k个元素。
使用 priority_queue<int,vector<int>,greater<int> > q(arr,arr+m);
时间复杂度:O(n*lg(k))

4、分治法
分治法(Divide&Conquer),把一个大的问题,
转化为若干个子问题(Divide),每个子问题“都”解决,
大的问题便随之解决(Conquer)。这里的关键词是“都”。从伪代码里可以看到,快速排序递归时,
先通过partition把数组分隔为两个部分,
两个部分“都”要再次递归。
分治法有一个特例,叫减治法,减治法(Reduce&Conquer),把一个大的问题,转化为若干个子问题(Reduce),这些子问题中“只”解决一个,大的问题便随之解决(Conquer)。
这里的关键词是“只”。

总结
全局排序,O(n*lg(n))
局部排序,只排序TopK个数,O(n*k)
堆,TopK个数也不排序了,O(n*lg(k))
分治法,每个分支“都要”递归,例如:快速排序,O(n*lg(n))
减治法,“只要”递归一个分支,例如:二分查找O(lg(n)),随机选择O(n)
TopK的另一个解法:随机选择+partition

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值