100万个数中找出最大的前K个数

拿到这个题目我想到了很多方法,但是在我想到的方法中,要把在100万个数中找到前k个数,都不适用。最后通过我的不断研究,我想到了我认为最简单的方法,就是利用堆来做这道题目。

下面我分析一下我用堆排序的思路:

1.我先建一个大小为k的堆。

2.把100万中前k个数放到这个堆中。

3.把这个堆调成小堆。

4.把100万个从k到100万之间的数字拿出来和堆的根结点作比较。

5.如果根结点小于这之间的某一个数,就把这个数拿给根结点,然后继续调成小堆。否则继续找

6.直到找完这100万个数,堆中放的就是最大的前k个数。

代码如下:

//下调
void _AdjustDown(int *arr, int parent, int size)
{
	int child = 2 * parent + 1;
	while (child<size)
	{
		//child + 1 < size保证是最后一个节点
		if (child + 1 < size&&arr[child] > arr[child + 1])
		{
			child++;//保证是孩子结点最大的一个节点
		}
		//交换
		if (arr[child] < arr[parent])
		{
			swap(arr[child], arr[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}
int* Find(int *arr, int k,int N)
{
	assert(arr);
	assert(k > 0);
	int *str = new int[k];
	//把前k个元素放在堆中
	for (int i = 0; i < k; i++)
	{
		str[i] = arr[i];
	}
	//调成最小堆
	for (int j = (k - 2) / 2; j >= 0; j--)
	{
		_AdjustDown(str, j, k);
	}
	//然后k到N的所有数与堆中的根结点相比较
	for (int n = k; n < N; n++)
	{
		if (str[0] < arr[n])//如果根结点小于堆中k到N中的某一元素
		{
			str[0] = arr[n];//把这个元素赋值给根结点
			_AdjustDown(str, 0, k);//再一次调成最小堆
		}
	}
	return str;
	delete[]str;
}

希望这个对你们有帮助。期待你们的回复,有什么不对的地方可以指出来啊。

时间: 2024-10-09 21:47:09

100万个数中找出最大的前K个数的相关文章

【海量数据处理】N个数中找出最大的前K个数

N个数中找出最大的前K个数,需要用小堆实现. 分析:由于小堆的堆顶存放堆中最小的数据,可以通过与堆顶数据进行比较,将大数据存放在堆中,注意在每次改变堆顶数据后,进行调堆,使堆顶一直存放整个堆中最小元素. void AdjustDown(int *a, size_t root, size_t size)//下调 {//小堆 size_t parent = root; size_t child = parent * 2 + 1; while (child < size) { if (child + 

C++100w个数中找出最大的前K个数

#include <iostream> using namespace std; #include <assert.h> const int N = 10000; const int K = 100; void AdjustDown(int topK[], int size, size_t parent) { assert(topK); int child = parent*2 + 1; while (child < size) { if (child+1 < size

面试题-10亿个数中找出最大的10000个数(top K问题)

一个较好的方法:先拿出10000个建立小根堆,对于剩下的元素,如果大于堆顶元素的值,删除堆顶元素,再进行插入操作,否则直接跳过,这样知道所有元素遍历完,堆中的10000个就是最大的10000个.时间复杂度: m + (n-1)logm = O(nlogm) 优化的方法:可以把所有10亿个数据分组存放,比如分别放在1000个文件中(如果是字符串hash(x)%M).对每个文件,建立大小为10000的小根堆,然后按有序数组的合并合并起来,取出最大的10000个即是答案. top K问题 在大规模数据

ytu 1061: 从三个数中找出最大的数(水题,模板函数练习 + 宏定义练习)

1061: 从三个数中找出最大的数Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 154  Solved: 124[Submit][Status][Web Board] Description 定义一个带参的宏(或者模板函数),从三个数中找出最大的数. Input 3个短整型数,空格隔开 3个实数,空格隔开 3个长整数,空格隔开 Output 最大的数,对于实数保留2位小数. Sample Input 1 2 3 1.5 4.7 3.2 123456

从有序矩阵M x N中找出是否包含某一个数,要求时间复杂度为O(M+N)

有序指的是每行从左到右依次变大,每列从上到下依次变大 思路: 从右上顶点开始依次判断当前值与给定值的大小,往左下顶点移动,结束条件是下标超过范围 public class FindNumInOrderMatr { public static void main(String[] args) { int[][] matrix = new int[][] { { 10, 12, 13, 15, 16, 17, 18 }, { 23, 24, 25, 26, 27, 28, 29 }, { 44, 4

poj2578---三个数中找出第一个大于168的

#include <stdio.h> #include <stdlib.h> int main() { int a,b,c; scanf("%d %d %d",&a,&b,&c); if(a <= 168) { printf("CRASH %d\n",a); return 0; } if(b <= 168) { printf("CRASH %d\n",b); return 0; } if

[面试题]在数组中找出3个数使得它们和为0

给定一个数组S,试找出3个数a, b, c,使得a+b+c=0.也即从集合中找出所有的和为0的3个数. 例如:集合S={-1,0, 1, 2, -1, 4},则满足条件的3个数有2对:(-1, 0, 1)和(-1, 2, -1).注意(-1,1,0)与(-1,0,1)算同一个解,所以不用重复考虑. 当然该例子集合的解也可以写成:(0, 1, -1)和(2, -1, -1). 参考了:http://blog.csdn.net/wangran51/article/details/8858398,他给

找出一堆数中最小的前K个数

描写叙述: 给定一个整数数组.让你从该数组中找出最小的K个数 思路: 最简洁粗暴的方法就是将该数组进行排序,然后取最前面的K个数就可以. 可是,本题要求的仅仅是求出最小的k个数就可以,用排序能够但显然有点浪费.比方让求10000个整数数组中的最小的10个数.用排序的话平均时间复杂度差为Nlog(N). 于是想到了,用堆来实现,可是自己实现又太麻烦.想到了java里面的TreeSet,先将K个数放入TreeSet中.因为TreeSet会对里面的元素进行排序.所以在TreeSet中的元素是有序的.以

数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数

问题描述: 数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数. 算法一: 对数组a[n]进行冒泡排序,如果冒泡所得的最值和前一个最值相等,则该最值为重复的数. 分析: 该算法时间复杂度最坏的情况为O(n的2次方),在空间开销上只需要一个额外的交换空间. 如何将时间开销减小呢?下面给出另外一种算法 算法二: 给定另外一个数组b[n],将a[n]中的数作为数组b的索引,然后遍历b[n],如果未访问过,则标记:如果已经访问过,则该索引就为重复的数. 分析: 该算法时间复杂度能够达到最