最大堆 第k个最大的元素 女生一晚最多啪多少次比较多少次

查找(27)
给定一个最大堆,找出第k大的节点。
建一个最小堆 minHeap来解决此题.
& & 1 取最大堆的根节点,放入minHeap;
& & 2 移除minHeap的根节点,并把该根节点在最大堆的两个子节点插入minHeap(插入过程保证heap的性质);
& & 3 回到1.2 步。
minHeap的节点数在不断增加,但是不会超过2k。minHeap插入节点的复杂度是O(2k)=O(k)。整个算法的复杂度是kO(k)。
类似题目:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:564118次
积分:8725
积分:8725
排名:第2162名
原创:279篇
转载:86篇
译文:19篇
评论:35条
(12)(12)(7)(9)(61)(32)(1)(26)(1)(2)(53)(28)(2)(26)(73)(23)(4)(2)(4)(2)(4)寻找最大的K个数
  有很多个无序的数,怎么选出其中最大的若干个数?
  即,从n个数中选出最大的K个数。
  先假设元素的数量不大,例如在几千个左右,在这种情况下,我们就排序吧。
  在这里,快速排序或堆排序都是不错的选择,他们的平均时间复杂度都是O(nlog2n),然后取出钱K个,O(K)。
  总的时间复杂度仍然是O(nlog2n)。
  可以注意到,即便是K=1的情况,上面的算法复杂度仍然是O(nlog2n),而显然,我们可以通过n-1此的比较和交换得到结果,不需要对整个数组进行排序。
  要避免做后面n-K个数的排序,可以使用部分排序算法,选择排序和冒泡排序都是不错的选择。
  把n个数中的前K个数排序出来,复杂度是O(n*K)。
  哪一个更好呢?O(nlog2n) 和O(n*K)?这取决于K的大小,在K&log2n的情况下,可以选择部分排序。
  回忆一下快速排序,快排中的每一步,都是将数据分为两组,其中一组的任何数都小于另一组中的任何数,不断地对数据进行分割直到不能再分即完成排序。
  假设n个数存储在数组S中,从S中找出一个元素X,它把数组分为比它大的和比它小的两部分,假设比它大的一部分数组是Smax,比它小的部分是Smin。
  这时有两种可能:
  1.Smax中元素不足K个,说明Smax中的所有数和Smin中最大的K-|Smax|个元素就是数组S中最大的K个数;
  2.Smax中元素的个数大于或等于K,则需要返回Smax中最大的K个元素。
  这样递归下去,问题的规模不断地变小,平均时间复杂度O(n * log2K)。
  寻找n个数中最大的K个数,本质上就是寻找这K个数中最小的那个,也就是第K大的数。
  可以使用二分搜索的策略。对于一个给定的数p,可以在O(n)的时间复杂度内找出所有不小于p的数。
  (此方法详述部分略)。
解法四:如果N非常非常大呢?
  前面三个解法都需要对数据访问多次,如果n很大呢?100亿?这个时候数据不能全部装入内存,所以要求尽可能少地遍历所有数据。
  前K个数中最大的K个数是一个退化的情况,所有K个数就是最大的K个数,如果考虑第K+1个数,则它和前面K个数的最小值进行比较,比其大则替换它。
  如果用一个数组来存储最大的K个数,每加入一个数X,就扫描一遍数组,得到数组中最小的数Y。X和Y进行比较,替换它或者保持原数组不变。这种方法,所耗费的时间复杂度为O(n * K)。
  进一步,可以用容量为K的最小堆来存储最大的K个数。最小堆的堆顶元素就是最大K个数中最小的一个。每次新考虑一个数X,如果X小于堆顶则舍弃,如果X大于堆顶,那么用X替换堆顶,然后更新堆来维持堆的性质。(因为X可能并不是最小值,所以堆结构需要更新)。更新过程花费的时间复杂度为O(log2K)。
  因此,算法的时间复杂度为O(n * log2K),这实际上是部分执行了堆排序的算法。
  如果所有n个数都是整数,且它们的取值范围不太大,可以考虑申请空间,记录每个整数出现的次数,然后再从大到小取最大的K个。
  比如用数组count,count[i]表示整数i出现的次数。
  极端情况下,如果n个整数各不相同,只需要一个bit来存储这个整数是否存在。
  实际情况下,并不一定能保证所有元素都是正整数,且取值范围不太大。但是这种方法仍然可以推广适用。比如把取值区间分成多块,然后统计各个小区间中元素的个数。可以知道第K大的元素在哪一个小区间,然后再对那个小区间继续进行分块处理。
  《编程之美》2.5节。
  本题目其他相关链接:
  链接1:
  链接2:
  本博客关于排序算法的回顾:
  排序算法:
阅读(...) 评论()

我要回帖

更多关于 女生一晚最多啪多少次 的文章

 

随机推荐