2.5 寻找最大的K个数

解法一:

设元素的数量不大,用快排或堆排序都是不错选择,平均时间复杂度都是O(N*log N)。然后取出前K个,O(K)。总时间复杂度O(N*log N)+ O(K)=O(N* log N)。

当K=1,上述算法也是O(N* log N)的复杂度,而显然我们可以通过N-1次的比较和交换得到结果。上述算法对整个数组都进行了排序,而原题目只要求最大的K个数,并不需要前K个数有序,也不需要前K个数有序,也不需后N-K个数有序。

如何避免后N-K个数的排序呢?我们需要部分排序算法,选择排序和交换排序都可以。把N个数中的前K个数排序出来,复杂度是O(N*K).


上述哪一种更好?O(N* log N) 还是 O(N*K)? 这取决于K的大小,需要从面试官那里弄清楚。在K<= log N时,选择部分排序。


解法二:

设N个数存储在数组S中,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中所有元素都大于等于X,Sb中所有元素小于X。

1)Sa中元素的个数小于K,Sa中所有的数和Sb中最大的K-|Sa|个元素 (|Sa|指Sa中元素的个数)就是数组S中最大的K个数。

2)Sa中元素的个数大于或等于K,则需要返回Sa中最大的K个元素。

这样递归下去,不断把问题分解成更小问题,平均时间复杂度O(N*log k).


解法三:

寻找N个数中最大的K个数,本质上就是寻找最大的K个数中最小的那个,那就是第K大的数。可以使用二分搜索的策略。对于一个给定的数p,可以在O(N)的时间复杂度内找出所有不小于p的数。假如N个数中最大的数是Vmax,最小的数位Vmin,那么这N个数中的第K大数一定在区间[Vmin,Vmax]之间。那么可以,在这个区间内二分搜索N个数中的第K大数p。

while(Vmax - Vmin > delta) {
	Vmid = Vmin +(Vmax - Vmin) * 0.5;
	if(f(arr, N, Vmid) >= k) 
		Vmin=Vmid;
	else
		Vmax=Vmid;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值