topK 算法
搜索引擎热门查询统计
题目描述:
搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。
假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。
分析:
这个问题在之前的这篇文章十一、从头到尾彻底解析Hash表算法里,已经有所解答。方法是:
第一步、先对这批海量数据预处理,在O(N)的时间内用Hash表完成统计
第二步、借助堆这个数据结构,找出Top K,时间复杂度为N‘logK。
即,借助堆结构,我们可以在log量级的时间内查找和调整/移动。因此,维护一个K(该题目中是10)大小的小根堆(K1>K2>....Kmin,Kmin设为堆顶元素),然后遍历300万的Query,分别和根元素Kmin进行对比比较(如上第2节思路3所述,若X>Kmin,则更新并调整堆,否则,不更新),我们最终的时间复杂度是:O(N) + N'*O(logK),(N为1000万,N’为300万)。更多详情请参考原文。
代码实现:
#include <stdio.h>
#include <stdlib.h> #define MAXLEN 100005
#define K 100 void Swap(int* a, int* b) {
*a=*a^*b;
*b=*b^*a;
*a=*a^*b;
} void HeapAdjust(int array[], int i, int length) {
int child, temp;
for(temp = array[i]; *i+<length; i=child) {
child = *i+;
if(child < length- && array[child+] < array[child])
child++;
if (temp > array[child])
array[i] = array[child];
array[child] = temp;
}
} int GetMin(int array[], int length, int k) {
int min = array[];
Swap(&array[], &array[length-]); int child, temp;
int i=, j=k-;
for (temp = array[]; j> && *i+<length; --j,i=child) {
child = * i + ;
if (child < length - && array[child+] < array[child])
child++;
if (temp > array[child])
array[i] = array[child];
else
break;
array[child] = temp;
}
return min;
} void Kmin(int array[] , int length , int k) {
for(int i=length/-;i>=;--i)
//初始建堆,时间复杂度为O(n)
HeapAdjust(array,i,length); int j=length;
//k次循环,每次循环的复杂度最多为k次交换,复杂度为o(k^2)
for(int i=k;i>;--i,--j){
int min=GetMin(array,j,i);
printf("%d,", min);
}
} int main() {
int array[MAXLEN];
for(int i=MAXLEN; i>; --i) { // init array
array[MAXLEN - i] = i;
}
Kmin(array, MAXLEN, K);
return ;
}
ref: http://blog.csdn.net/v_JULY_v/article/details/6256463
http://blog.csdn.net/v_JULY_v/article/details/6403777
topK 算法的更多相关文章
- 关于堆排序和topK算法的PHP实现
问题描述 topK算法,简而言之,就是求n个数据里的前m大个数据,一般而言,m<<n,也就是说,n可能有几千万,而m只是10或者20这样的两位数. 思路 最简单的思路,当然是使用要先对这n ...
- java TopK算法
现有一亿个数据,要求从其中找出最小的一万个数,希望所需的时间和空间最小,也就是所谓的topK问题 TopK问题就是从海量的数据中取最大(或最小的)的K个数. TopK问题其实是有线性时间复杂度的解的, ...
- (转)基于快速排序的TOPK算法
基于快速排序的TOPK算法 转自:http://blog.csdn.net/fanzitao/article/details/7617223 思想: 类似于快速排序,首先选择一个划分元,如果这个划分元 ...
- topk算法
方法一 堆排序 自建堆 heapMax方法,从上至下调整堆 pop时,可以使用自上而下调整堆,调用heapMax(arr,0,sz-1); push时,需要自下到上调整即 从上到下调整: void h ...
- Python 实现转堆排序算法原理及时间复杂度(多图解释)
原创文章出自公众号:「码农富哥」,欢迎转载和关注,如转载请注明出处! 堆基本概念 堆排序是一个很重要的排序算法,它是高效率的排序算法,复杂度是O(nlogn),堆排序不仅是面试进场考的重点,而且在很多 ...
- 大数据热点问题TOP K
1单节点上的topK (1)批量数据 数据结构:HashMap, PriorityQueue 步骤:(1)数据预处理:遍历整个数据集,hash表记录词频 (2)构建最小堆:最小堆只存k个数据. 时间复 ...
- 大数据计算:如何仅用1.5KB内存为十亿对象计数
大数据计算:如何仅用1.5KB内存为十亿对象计数 Big Data Counting: How To Count A Billion Distinct Objects Using Only 1.5K ...
- HashTable和HashSet中的类型陷阱
HashTable和HashSet中的类型陷阱 发现这个陷阱的起因是这样的:我现在有上百万字符串,我准备用TopK算法统计出出现次数做多的前100个字符串. 首先我用Hashtable统计出了每个字符 ...
- sdn测量论文简介
Prelude: Ensuring Inter-Domain Loop-Freedom in SDN-Enabled Networks 来源:APNet: The Asia-Pacific Works ...
随机推荐
- c++ primer读书笔记之c++11(四)
1 带有作用域的枚举 scoped-enumeration 相信大家都用过枚举量,都是不带有作用域的,在头文件中定义需要特别注意不要出现重名的情况.为了解决这种问题,c++11提供了带作用于的枚举. ...
- 【Bootstrap Method】Evaluating The Accuracy of a Classifier
自助法介绍: 非参数统计中一种重要的估计统计量方差进而进行区间估计的统计方法,也称为自助法.其核心思想和基本步骤如下:(1)采用重抽样技术从原始样本中抽取一定数量(自己给定)的样本,此过程允许重复抽样 ...
- scala工程导入报错:scalatest_2.10-1.9.1.jar is cross-compiled with an incompatible version of Scala (2.10).
错误原因: The Scala IDE tries to check if binary incompatible Scala libraries have been inadvertently mi ...
- Oracle报错:ORA-06508: PL/SQL: 无法找到正在调用的程序单元
原因:调用的存储过程已经被修改过. 解决方案:重新编译存储过程.
- 在IIS中访问APS页面时提示:“最可能的原因使用的托管的处理程序,但是未安装或未完整安装asp.net“
打开CMD窗口,执行下面的命令: "%WINDIR%\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe" -iru -ena ...
- MySQL——SQL Mode详解
简介 MySQL服务器能够工作在不同的SQL模式下,并能针对不同的客户端以不同的方式应用这些模式.这样,应用程序就能对服务器操作进行量身定制以满足自己的需求.这类模式定义了MySQL应支持的SQL语法 ...
- 树莓派3B+首次登陆通过网络
树莓派3B+默认串口不能登录,即使可使用可需要通过连线方式连接,如何才能直接通过网络ssh登录树莓派呢? 串口问题及使用 树莓派3的UART串口的使用问题,该串口问题的官方反馈及回复请参考这两篇官方博 ...
- 【进阶修炼】——改善C#程序质量(9)
140,使用默认的访问修饰符. 如果不加访问修饰符,成员变量的默认是private的,类默认是internal的.为了明确访问的权限,我倒是建议都加上访问修饰符,这省不了多少代码. 141,不知道该不 ...
- buzhoutiao
基于SUI前端框架 前台HTML: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " ...
- avcodec_open2()分析
该函数用于初始化一个视音频编解码器的AVCodecContext. int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVD ...