Top k 问题

Top K的问题:

给出大量数据,找出其中前K个最大(小)的数,或者在海量数据中找到出现频率最好的前K个数。

一、给出大量数据(N个),找出其中前K个最大数(没有其他资源上的限制)

1、使用排序算法

  直接使用排序算法,如快速排序,然后遍历找到最大的K个数。时间复杂度为O(NlogN);

2、部分排序

  因为,只要求出前K个最大值,所以我们不必全部排好。思路是:随意选出K个数形成一个数组,然后按从大到小进行排序,再从剩下的数中,选取一个数和数组中的最小值进行比较,若小于最小值,则取下一个数继续比较;若大于,则遍历数组找到相应的位置,淘汰掉数组中的最小值。反复操作直到遍历完所有数。这里更新一个数,会导致数组中后面数的移动,也增加了时间复杂度。时间复杂度为O(N*K)

3、堆排序

  思想和方法2类似,思路如下:

 (1)可任取K个数,形成最小堆;时间复杂度为O(KlogK)。

 (2)从剩下的数中,选出一个数和最小堆的堆顶元素比较,若大于堆顶元素,则说明此时该数为最大的K个数中的一个,若小于则比较下一个数;

 (3)调整最小堆。时间复杂度为O(logK),K为常数;

 (4)重复(2)~(3),直到所有数都完成。时间复杂度为O(NlogK)。

 3.1最小堆(动态示意图)实现代码如下:

 1 /*调整堆*/
 2 void minHeapFy(int *heap, int i, int heapSize)
 3 {
 4     int parent = i;
 5     int lChild = 2 * i + 1;
 6     int rChild = 2 * i + 2;
 7     int index = lChild;
 8     while (rChild<heapSize)
 9     {
10         if (rChild<heapSize&&heap[lChild]>heap[rChild])
11             index++;
12         if (heap[parent]<heap[index])
13             return;
14         else
15         {
16             swap(heap[parent], heap[index]);
17             parent = index;
18             lChild = 2 * parent + 1;
19             rChild = lChild + 1;
20             index = lChild;
21         }
22     }
23 }
24
25 /*建最小堆*/
26 void buildHeap(int *heap, int n)
27 {
28     for (int i = n / 2-1 ; i >= 0; i--)
29     {
30         minHeapFy(heap, i, n);
31     }
32 }
33
34 /*n为Top_K 的值,N为海量数据数*/
35 void minHeapSort(int *heap, int n, int *arr)
36 {
37     int N=30;                        //海量数据初始值
38     buildHeap(heap, n);          //先用n个元素建好堆
39
40     for (int i = n; i<N;++i)
41     {
42         if (arr[i]>heap[0])
43         {
44             heap[0] = arr[i];
45             minHeapFy(heap, 0, n);
46         }
47     }
48 }

整个问题的完全代码见这里

二、统计最热门查询,首先就是要统计每个Query出现的次数,然后根据统计结果,找出Top K

  问题描述(题目来源v_JULY_v

  百度面试题:

  搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。

  假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。

  解决步骤:

1、Query统计

  因为题中有提到重复度比较高,所以可以维护一个key为Query的字符串,value是Query出现次数的哈希表,每次读取一个Query,如果该字符串不在哈希表中,那么加入该字符串,并将value值设为1;如果在对应字符串的计数加1即可。时间复杂度为O(N)。

2、找出Top K

  利用问题一中提到的最小堆排序可以实现。时间复杂度为O(N)+O(nlogK),其中n为不重复的查询串。

三、海量数据处理---10亿数中找到最大的10000个数(文章地址YoferZhang

  1、使用最小堆排序,具体过程如问题一中算法3。时间复杂度为O(nlogn)+O(Nlogn)。其中N为1亿,n为10000。

  2、优化

  将10亿个数据分组存放,比如分成M组,然后每一组数据中找到Top K ,然后合并在一起,一块查找。查找过程使用最小堆排序。

注:Top K的问题,通常比较好的方案是分治+Trie树/hash+小顶堆。

另外,LaoJiu_ 提到的BFPRT算法解决Top K的问题,最坏的时间复杂度为O(n)。

有用的链接:

教你如何迅速秒杀掉:99%的海量数据处理面试题

程序员编程艺术:第三章续、Top K算法问题的实现

hadoop mapreduce 解决 top K问题

海量数据处理算法(top K问题)

BFPRT 算法(TOP-K 问题)

时间: 2024-12-08 11:41:18

Top k 问题的相关文章

排序算法Java版,以及各自的复杂度,以及由堆排序产生的top K问题

常用的排序算法包括: 冒泡排序:每次在无序队列里将相邻两个数依次进行比较,将小数调换到前面, 逐次比较,直至将最大的数移到最后.最将剩下的N-1个数继续比较,将次大数移至倒数第二.依此规律,直至比较结束.时间复杂度:O(n^2) 选择排序:每次在无序队列中"选择"出最大值,放到有序队列的最后,并从无序队列中去除该值(具体实现略有区别).时间复杂度:O(n^2) 直接插入排序:始终定义第一个元素为有序的,将元素逐个插入到有序排列之中,其特点是要不断的 移动数据,空出一个适当的位置,把待插

347. Top K Frequent Elements

Given a non-empty array of integers, return the k most frequent elements. For example,Given [1,1,1,2,2,3] and k = 2, return [1,2]. Note: 347. Top K Frequent ElementsYou may assume k is always valid, 1 ≤ k ≤ number of unique elements. Your algorithm's

Top K Frequent Words

Given a list of words and an integer k, return the top k frequent words in the list. Given [ "yes", "lint", "code", "yes", "code", "baby", "you", "baby", "chrome", &

Spark 编程实战之经典算法TOP K

Top K Top K算法有两步,一是统计词频,二是找出词频最高的前K个词. 1.实例描述 假设取Top 1,则有如下输入和输出. 输入: Hello World Bye World Hello Hadoop Bye Hadoop Bye Hadoop Hello Hadoop 输出: 词Hadoop 词频4 2.设计思路 首先统计WordCount的词频,将数据转化为(词,词频)的数据对,第二个阶段采用分 治的思想,求出RDD每个分区的Top K,最后将每个分区的Top K结果合并以产生新的集

Top K问题!!!!!!!!!!!!!

转:http://blog.csdn.net/boo12355/article/details/11788655 Top K 算法详解应用场景: 搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节.        假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个.一个查询串的重复度越高,说明查询它的用户越多,也就是越热门.),请你统计最热门的10个查询串,要求使用的内存不能超过1G. 必备知识:什么

Top k问题的讨论(三种方法的java实现及适用范围)

在很多的笔试和面试中,喜欢考察Top K.下面从自身的经验给出三种实现方式及实用范围. 合并法 这种方法适用于几个数组有序的情况,来求Top k.时间复杂度为O(k*m).(m:为数组的个数).具体实现如下: /** * 已知几个递减有序的m个数组,求这几个数据前k大的数 *适合采用Merge的方法,时间复杂度(O(k*m); */ import java.util.List; import java.util.Arrays; import java.util.ArrayList; public

Top K and Quick Selection

The common solutions for top k problem are heap (priority queue) and quick selection. Using heap is very straight-forward, while quick selection with partition is more complicated and I didnot find any satisfying code online, so document as following

Top k Largest Numbers

Given an integer array, find the top k largest numbers in it. Example Given [3,10,1000,-99,4,100] and k = 3.Return [1000, 100, 10]. 思路:由于需要按从大到小的顺序,因此直接用PriorityQueue即可,用Partition的方法的话还需要排序.直接用PriorityQueue 写的代码量少. 1 class Solution { 2 /* 3 * @param

Top k问题(线性时间选择算法)

问题描述:给定n个整数,求其中第k小的数. 分析:显然,对所有的数据进行排序,即很容易找到第k小的数.但是排序的时间复杂度较高,很难达到线性时间,哈希排序可以实现,但是需要另外的辅助空间. 这里我提供了一种方法,可以在O(n)线性时间内解决Top k问题.关于时间复杂度的证明,不再解释,读者可以查阅相关资料.具体的算法描述如下: 算法:LinearSelect(S,k) 输入:数组S[1:n]和正整数k,其中1<=k<=n: 输出:S中第k小的元素 1. If  n<20  Then