有5亿个int范围的数字,量太大不能直接存放到内存下,如何处理可以找出中位数
一般这种问题,可以考虑用分支的思想。
1、由于不能直接放在内存里,先将这int范围的数字划分成2^16个区,第一个区的范围是[0 , (2^32-1) / (2^16)),以此类推。
2、然后读入数据,分别将其累加到相应的分区。
3、依次统计分区,读到累加数字个数大于等于2.5亿的时候,说明中位数在这个分区。
4、重新读取所有数据,添加在这个分区范围的数据到数组中,对该数组排序就可以得到中位数了。
//有5亿个数字,量太大不能直接存放到内存下,如何处理可以找出中位数 #include<stdio.h> #include<iostream> #include<algorithm> using namespace std; int hash[128*128]; int shu[1000000]; int main(){ int i,n=1<<32-1,m=128*128,temp; double second; for(i=0;i<m;i++){ hash[i]=0; } for(i=0;i<i;i++){ scanf("%d",&temp); second=m*temp/n; hash[(int)second]++; } int add=0 , end = n>>1; for(i=0;i<m;i++){ add+=hash[i]; if(add >= end){ break; } } int left = (int) (n*1.0/m * (i-1)); int right= (int) (n*1.0/m * i); int num=0; for(i=0;i<n;i++){ scanf("%d",&temp); if(temp>=left && temp<=right){ shu[add]=temp; add++; } } sort(&shu[0],&shu[add]); if(add%2 == 0) printf("%d\n",(shu[add/2-1]+shu[add/2])/2); else printf("%d\n",shu[add/2]); return 0; }
某网站每周都有很多浏览数据,每条PV日志都存一个1到2^63-1的数字表示浏览商品的ID。现在有10亿条PV日志文件,已知商品库中有5亿个不重复的商品,给你一台内存为2GB的电脑,让你找出哪些商品没有被浏览过。
同样,考虑分支的思想。
1、先将这long long 范围的数字划分成2^16个区,第一个区的范围是[0 , (2^32-1) / (2^16)),以此类推。
2、将PV日志中的商品 与 商品库中的商品 分别放在硬盘下对应的2^16个文件中
3、在第一个文件,排序PV日志中的商品 与 排序商品库中的商品,比较下,即可找出这个文件下那些商品未被浏览过。然后处理下一个文件。
有5亿个商品成交数据,让你找出销量最高的10000个商品
5亿商品的id如果不大,可以直接放在内存中的话,可以先建表统计相应的商品的个数,然后建一个大小为10000的小顶堆,更新即可。
如果5亿商品的id比较大,不容易直接放到内存里,那就先分治,将数据按id范围分到N个硬盘的文件下,对单个文件里的商品排序统计,更新到小顶堆,在对其他文件依次处理。
总结:这类大数据的题目,一般用分支,在转化数据量足够小了可以在内存中处理了,在依次处理。