需求

从一亿个数据中,找出其中最小的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算法的更多相关文章

  1. 百度面试题——top K算法

    需求 从一亿个数据中,找出其中最小的10个数. 分析 最笨的方法就是将这一亿个数据,按从小到大进行排序,然后取前10个.这样的话,即使使用时间复杂度为nlogn的快排或堆排,由于元素会频繁的移动,效率 ...

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

    程序员编程艺术:第三章续.Top K算法问题的实现 作者:July,zhouzhenren,yansha.     致谢:微软100题实现组,狂想曲创作组.     时间:2011年05月08日    ...

  3. Top K 算法详解

    http://xingyunbaijunwei.blog.163.com/blog/static/7653806720111149318357/ 问题描述         百度面试题:        ...

  4. Top K算法

    应用场景: 搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节.        假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果 ...

  5. hihoCoder 1133 二分·二分查找之k小数(TOP K算法)

    #1133 : 二分·二分查找之k小数 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回里我们知道Nettle在玩<艦これ>,Nettle的镇守府有很 ...

  6. 使用堆实现Top K 算法 JS 实现

    1. 堆算法Top,时间复杂度 O(LogN) function top(arr,comp){ if(arr.length == 0){return ;} var i = arr.length / 2 ...

  7. top k 算法

    对于一个非有序的数组A[p..r],求数组中第k小的元素. 如何考虑 排序(部分排序)就不用说了..o(nlgn),当然如果在实际情况中要一直取值,当然要排序后,一次搞定,以后都是O(1) 我们这里提 ...

  8. Top K问题-BFPRT算法、Parition算法

    BFPRT算法原理 在BFPTR算法中,仅仅是改变了快速排序Partion中的pivot值的选取,在快速排序中,我们始终选择第一个元素或者最后一个元素作为pivot,而在BFPTR算法中,每次选择五分 ...

  9. 04Top K算法问题

    本章阐述寻找最小的k个数的反面,即寻找最大的k个数,尽管寻找最大的k个树和寻找最小的k个数,本质上是一样的.但这个寻找最大的k个数的问题的实用范围更广,因为它牵扯到了一个Top K算法问题,以及有关搜 ...

随机推荐

  1. nmon Analyser分析仪

    nmon Analyser官网: https://www.ibm.com/developerworks/community/wikis/home?lang=en#!/wiki/Power+System ...

  2. fiddler抓包-简单易操作(一)

    1.下载fiddler 可以到fiddler官网去下,网址:https://www.telerik.com/download/fiddler 下载完成后,安装即可. 2.运行fiddler,进入fid ...

  3. Web负载均衡技术

    Web负载均衡(Load Balancing),简单地说就是给我们的服务器集群分配“工作任务”,而采用恰当的分配方式,对于保护处于后端的Web服务器来说,非常重要. 负载均衡的策略有很多,我们从简单的 ...

  4. LLLYYY的数字思维(模拟题)

    链接:https://ac.nowcoder.com/acm/contest/318/G LLLYYY很喜欢写暴力模拟贪心思维.某一天在机房,他突然抛给了队友ppq一 个问题.问题如下: 有一个函数f ...

  5. tensorflow Importing Data

    tf.data API可以建立复杂的输入管道.它可以从分布式文件系统中汇总数据,对每个图像数据施加随机扰动,随机选择图像组成一个批次训练.一个文本模型的管道可能涉及提取原始文本数据的符号,使用查询表将 ...

  6. springMVC前后台数据交互

    假设项目需求是在springMVC框架下,后台要传送一个list到前台,那我们就要做以下几个步骤: 1 在web.xml文件中进行springMVC的配置: <?xml version=&quo ...

  7. clone项目到本地

    clone项目到本地 1.然后在本地建立接受代码的文件夹,然后cd 到这个目录 (克隆版本库的时候,所使用的远程主机自动被git命名为origin.如果想用其他的主机名,需要用git clone命令的 ...

  8. ASP.NET页面之间传值Server.Transfer(4)

    这个才可以说是面象对象开发所使用的方法,其使用Server.Transfer方法把流程从当前页面引导到另一个页面中,新的页面使用前一个页面的应答流,所以这个方法是完全面象对象的,简洁有效. Serve ...

  9. P4109 [HEOI2015]定价

    题目描述 在市场上有很多商品的定价类似于 999 元.4999 元.8999 元这样.它们和 1000 元.5000 元和 9000 元并没有什么本质区别,但是在心理学上会让人感觉便宜很多,因此也是商 ...

  10. JS格式化 /Date(xxxxxx)/的日期类型

    //用来转换/Date(xxxxxx)/类型的JSON日期为要求的日期格式字符串String.prototype._formatJsonDate = function (format) { var s ...