百度面试题——top K算法
需求
从一亿个数据中,找出其中最小的10个数。
分析
最笨的方法就是将这一亿个数据,按从小到大进行排序,然后取前10个。这样的话,即使使用时间复杂度为nlogn的快排或堆排,由于元素会频繁的移动,效率也不会是最高的。
实际上我们可以维护一个大小为10的大顶堆,开始可以就将数列中的前10个数用来建堆,根元素最大。之后遍历剩余的数,分别将其与根元素进行比较,只要小于根元素,就将该数替代原来的根元素,成为新的根元素,之后adjustdown该堆,则该堆的根元素又是堆中最大的数据了。
测试代码如下
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> static void show(int *arr, int len)
{
int index;
for(index = 0; index < len; index++)
{
printf("%d ",arr[index]);
}
printf("\n");
} static void swap(int *left, int *right)
{
int tmp = *left;
*left = *right;
*right = tmp;
} void adjustdown(int *arr, int i, int end)
{
int key = arr[i];
int p = i;
int left = 2 * p + 1;
/* 越界就是没孩子 */ /* 只要能进循环,一定有左孩子 */
while( left <= end )
{
/* 有右孩子的情况下,大于等于左右孩子不用换 */
if( (key >= arr[left]) && (left+1 <= end && key >= arr[left+1]))
{
break;
}else if( key >= arr[left] && left + 1 > end) /* 没有右孩子,只有左孩子,且大于等于左孩子不用换*/
{
break;
}else if(left + 1 <= end && arr[left+1] >= arr[left] && key < arr[left+1]) /* 与右孩子换。要保证有右孩子,且右孩子大于等于左孩子,父亲小于右孩子 */
{
swap(arr+p, arr+left+1);
p = left + 1; //父亲与谁换,就到谁的位置了
left = 2 * p + 1;//父亲新的左孩子的位置
}else if(left + 1 <= end && arr[left] > arr[left + 1] && key < arr[left])/* 与左孩子换。有右孩子的情况下,右孩子小于左孩子,父亲小于左孩子 */
{
swap(arr + p, arr + left);
p = left;
left = 2 * p + 1;
}else if(left + 1 > end && arr[left] > key) /* 与左孩子换。没右孩子的情况下,只需父亲小于左孩子 */
{
swap(arr + p, arr + left);
p = left;
left = 2 * p + 1;
}
}
} void heap_sort(int *arr, int len)
{
int p; // 最后一个父亲
int end; // 最后一个有效下标
/* 建一个大顶堆,从最后一个父亲开始调 */
for(p = (len -1 -1) /2 ; p >= 0; p--)
{
adjustdown(arr, p ,len - 1);
}
/* 根结点的值最大,与末尾交换,并继续建立堆结构,再交换... */
for(end = len - 1; end >= 1; end--)
{
swap(arr, arr + end ); // end已经是最大值
adjustdown(arr,0,end-1); // 从arr+1 到 end-1位置都是满足堆结构的
}
} void my_top(int *arr, int len, int top, int *arr_top, int top_len) //此处选最小的top个数,维护大堆。如果是最大top个数,就维护小堆。
{
/* 开始用插入排序 */ /* 不用插入排序,对arr_top直接建堆也是可以的 */
int index;
int pos;
for(index = 0; index < len; index ++)
{
if(index < top)
{
if(index == 0)
{
arr_top[index] = arr[index];
}else
{
/* 插入排序 */
//int pos; 从大到小
for(pos = index - 1; pos >= 0; pos--)
{
if(arr[index] >= arr_top[pos])
{
arr_top[pos + 1] = arr_top[pos];
}else
{
break;
}
}
arr_top[pos+1] = arr[index];
}
}else
{
if(arr[index] >= arr_top[0]) //比最大值还大,说明不是最小的10个数
{
continue;
}else
{
arr_top[0] = arr[index]; //淘汰掉原来最大的
adjustdown(arr_top,0,top_len-1); //重新选最大值 复杂度nlogn 但是这10个数并不是有序的
}
}
}
} int main(int argc, char *argv[])
{
int index;
int arr[20];
int arr_top[5];
memset(arr,0,20);
srand(time(NULL));
for(index = 0; index < 20; index++)
{
arr[index] = rand()%50+1;
}
show(arr,20); heap_sort(arr,20);
show(arr,20); my_top(arr,20,5,arr_top,5);
show(arr_top,5); system("pause");
return 0;
}
百度面试题——top K算法的更多相关文章
- 百度面试题——top K算法
需求 从一亿个数据中,找出其中最小的10个数. 分析 最笨的方法就是将这一亿个数据,按从小到大进行排序,然后取前10个.这样的话,即使使用时间复杂度为nlogn的快排或堆排,由于元素会频繁的移动,效率 ...
- 程序员编程艺术:第三章续、Top K算法问题的实现
程序员编程艺术:第三章续.Top K算法问题的实现 作者:July,zhouzhenren,yansha. 致谢:微软100题实现组,狂想曲创作组. 时间:2011年05月08日 ...
- Top K 算法详解
http://xingyunbaijunwei.blog.163.com/blog/static/7653806720111149318357/ 问题描述 百度面试题: ...
- Top K算法
应用场景: 搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节. 假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果 ...
- hihoCoder 1133 二分·二分查找之k小数(TOP K算法)
#1133 : 二分·二分查找之k小数 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回里我们知道Nettle在玩<艦これ>,Nettle的镇守府有很 ...
- 使用堆实现Top K 算法 JS 实现
1. 堆算法Top,时间复杂度 O(LogN) function top(arr,comp){ if(arr.length == 0){return ;} var i = arr.length / 2 ...
- top k 算法
对于一个非有序的数组A[p..r],求数组中第k小的元素. 如何考虑 排序(部分排序)就不用说了..o(nlgn),当然如果在实际情况中要一直取值,当然要排序后,一次搞定,以后都是O(1) 我们这里提 ...
- Top K问题-BFPRT算法、Parition算法
BFPRT算法原理 在BFPTR算法中,仅仅是改变了快速排序Partion中的pivot值的选取,在快速排序中,我们始终选择第一个元素或者最后一个元素作为pivot,而在BFPTR算法中,每次选择五分 ...
- 04Top K算法问题
本章阐述寻找最小的k个数的反面,即寻找最大的k个数,尽管寻找最大的k个树和寻找最小的k个数,本质上是一样的.但这个寻找最大的k个数的问题的实用范围更广,因为它牵扯到了一个Top K算法问题,以及有关搜 ...
随机推荐
- hdu 1212 Big Number
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1212 Big Number Description As we know, Big Number is ...
- JVM学习总结二——垃圾回收算法
昨天总结了JVM内存分区相关的知识,这次我们将来了解下JVM的另一个核心知识点——垃圾回收算法.这一部分其实并不太难,如果对操作系统的内存处理算法有所了解,那么这部分算法其实只看名字就能明白,两者在原 ...
- Spark 3000门徒第二课scala面向对象总结
昨晚听了王家林老师3000门徒spark系列课程的第二课,讲述了scala面向对象知识,并且带着过了一遍Spark核心类:SparkContent,RDD的代码,下面写一下心得: RDD是抽象类,实现 ...
- C语言函数返回数组
#include "stdio.h"/*int* set(int a,int *c){ int *b; b=malloc(sizeof(int)*3); c[0]=a; c[1]= ...
- Chr()和chrb()的含义(转)
http://blog.csdn.net/cunxiyuan108/article/details/5989701 Chr(charcode) 必要的 charcode 参数是一个用来识别某字符的 L ...
- 事后分析报告(M1阶段)
我们的项目是自选项目,一款名为备忘录锁屏MemoryDebris的软件. 因为我们组成员在此之前都没有接触过安卓开发,于是在第一阶段花了很大的时间和精力学习安卓.又花费了较长一段时间设计软件与研究安卓 ...
- 软件工程随堂作业--随机产生30到四则运算(c语言)
#include "stdio.h" #include "math.h" #include "stdlib.h" #include" ...
- “我爱淘”第二冲刺阶段Scrum站立会议1
完成任务: 完成了webservice的配置与测试,实现了在客户端的搜索功能,并且可以实现图书的发布功能,就是将图书的信息添加到数据库中. 计划任务: 在客户端实现分类功能,通过学院的分类查看书籍. ...
- 查看linux命令类型
type type -a type type是内建变量 root@akayer-p6:~# type -a lsls 是 `ls --color=auto' 的别名ls 是 /bin/ls
- svn 检出 Check out 请求的名称有效,但是找不到请求的类型的数据。
根据问题不同有不同的解决方案,可按照以下方法进行解决1.取消TortoiseSVN-网络-代理2.确认SVN目录地址是否正确,可在浏览器中直接打开测试.如地址是由计算机名组成请改成Ip地址进行测试