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

一个较好的方法:先拿出10000个建立小根堆,对于剩下的元素,如果大于堆顶元素的值,删除堆顶元素,再进行插入操作,否则直接跳过,这样知道所有元素遍历完,堆中的10000个就是最大的10000个。时间复杂度: m + (n-1)logm = O(nlogm)

优化的方法:可以把所有10亿个数据分组存放,比如分别放在1000个文件中(如果是字符串hash(x)%M)。对每个文件,建立大小为10000的小根堆,然后按有序数组的合并合并起来,取出最大的10000个即是答案。

top K问题

在大规模数据处理中,经常会遇到的一类问题:在海量数据中找出出现频率最好的前k个数,或者从海量数据中找出最大的前k个数,这类问题通常被称为top K问题。例如,在搜索引擎中,统计搜索最热门的10个查询词;在歌曲库中统计下载最高的前10首歌等。

解决方法:针对top K类问题,通常比较好的方案是分治+Trie树/hash+小顶堆(就是上面提到的最小堆),即先将数据集按照Hash方法分解成多个小数据集,然后使用Trie树或者Hash统计每个小数据集中的query词频或频数,之后用小顶堆求出每个数据集中出现频率最高的前K个数,最后在所有top K中求出最终的top K。

简陋的实现:

估计能处理1e8个整数(约400M)吧

#include<bits/stdc++.h>
using namespace std;

int n, k, tmp;
priority_queue<int, vector<int>, greater<int>>qu;

int main()
{
    scanf("%d%d", &n, &k);
    for(int i = 0;i < k;i++)
    {
        scanf("%d", &tmp);
        qu.push(tmp);
    }
    for(int i = 0;i < n-k;i++)
    {
        scanf("%d", &tmp);
        if(tmp > qu.top())
        {
            qu.pop();
            qu.push(tmp);
        }
    }
    for(int i = 0;i < k;i++)
    {
        printf("%d ", qu.top());
        qu.pop();
    }

    return 0;
}

参考链接:

1. CSDN_yofer张耀琦-海量数据处理 - 10亿个数中找出最大的10000个数(top K问题)

2. 牛客网-100w个数中找最大的100个数

原文地址:https://www.cnblogs.com/lfri/p/12422423.html

时间: 2024-10-08 11:03:56

面试题-10亿个数中找出最大的10000个数(top 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 + 

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

怎样从10亿查询词找出出现频率最高的10个

转自:http://dongxicheng.org/big-data/select-ten-from-billions/ 1. 问题描述 在大规模数据处理中,常遇到的一类问题是,在海量数据中找出出现频率最高的前K个数,或者从海量数据中找出最大的前K个数,这类问题通常称为“top K”问题,如:在搜索引擎中,统计搜索最热门的10个查询词:在歌曲库中统计下载率最高的前10首歌等等. 2. 当前解决方案 针对top k类问题,通常比较好的方案是[分治+trie树/hash+小顶堆],即先将数据集按照h

笔试题--在一个整数数组中找出第5大的数

/** * 在一个整数数组中找出第5大的数 * 思路是首先在数组中找到最小数,然后依次找到第五大的数 * * @param array * @return */ public static int[] selectionSort(int[] array) { if (array.length == 0) return array; for (int i = 0; i < array.length; i++) { int minIndex = i; for (int j = i; j < arr

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

拿到这个题目我想到了很多方法,但是在我想到的方法中,要把在100万个数中找到前k个数,都不适用.最后通过我的不断研究,我想到了我认为最简单的方法,就是利用堆来做这道题目. 下面我分析一下我用堆排序的思路: 1.我先建一个大小为k的堆. 2.把100万中前k个数放到这个堆中. 3.把这个堆调成小堆. 4.把100万个从k到100万之间的数字拿出来和堆的根结点作比较. 5.如果根结点小于这之间的某一个数,就把这个数拿给根结点,然后继续调成小堆.否则继续找 6.直到找完这100万个数,堆中放的就是最大

M个数里面找出最大的N个数

public class MaxnumNofM{ public static int[] MaxnumNofM(int BigArr[], int N ){     //取原始数组的前N个元素 int[] ResArr = new int[N];  for(int i=0; i<N;i++){ ResArr[i] = BigArr[i]; }        //标记上一轮是否发生过交换        boolean bExchanged = true;        //遍历后续的元素     

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

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

[面试题]在数组中找出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,他给