http://bbs.csdn.net/topics/310150772

可以借鉴一下以下方法的:

有1亿个浮点数,请找出其中最大的10000个。提示:假设每个浮点数占4个字节,1亿个浮点数就要站到相当大的空间,因此不能一次将全部读入内存进行排序。

  ~~~~~~~~~~~~~

  既然不可以一次读入内存, 那可以这么试试:

  方法1: 读出100w个数据, 找出最大的1w个, 如果这100w数据选择够理想, 那么以这1w个数据里面最小的为基准, 可以过滤掉1亿数据里面99%的数据, 最后就再一次在剩下的100w(1%)里面找出最大的1w个咯~~

  方法2: 分块, 比如100w一个块, 找出最大1w个, 一次下来就剩下100w数据需要找出1w个了.(注意消重,这剩下的100w个数据应该是互不相同的。即每找出一个块里最大的1w个,就应该hash存储。下一个块中若出现了已存储的数据,则不计在此块的top 1w里,这样才能保证最终剩下的100w里面寻找top 1w就接近1亿里面的top 1w。想想:如果每个块的top 1w都基本是重复的,不消重的话,最终的结果有可能就少于1w个。)

  对于上面提到的找出100w个数据里面最大的1w个, 说起来比较罗嗦, 还是说说找到第1w个大的数字的方法:

  用快速排序的方法, 分2堆, 如果大的那堆个数N大于1w个, 继续对大堆快速排序一次分成2堆, 如果大堆个数N小于1w, 就在小的那堆里面快速排序一次, 找第10000-N大的数字; 递归以上过程, 就可以找到第1w大的数. 据说也是STL的search_n()的方法;(更好的一种类似的方法是将这些数以5个为一组,每组通过插入排序找出其中位数,再找出其中位数的中位数,依次递归,找出最终一个中位数x,然后按照x对序列进行快排,且设x是序列的第k大的数,如果要找的是第i大的数,则比较k与i的关系,如果相等,直接返回x,否则如果k>i,则在小的那堆里面继续按照这种方式快排,如果k<i,则在大堆里面找第i-k大的数。)

  参考上面的找出第1w大数字, 相信楼主就可以类似的方法找出前1w大数字了

真的很感谢有这么多人回答,我的思路就是基本上排序+分块,
首先1亿个数我分成了200块,每块50W个,对每个块进行多路归并排序(这里不考虑快速排序,相对来说比较低率,不稳定),
排序好后存储在硬盘文件。
我写了下,大约是15S左右,
然后在用一个两维数组记录这200组数据中的最大和最小值,然后把这200个中位数的平均数求出来,其实没有别的目的
(目的是为了找一个适合的中位数偏移点,因为这个平均数不一定就是1亿个数的,可以叫做先猜一个机率最大的吧)
如果我们这么时候求得的平均数是N
然后就是一个超级土的试探法了,
建立一个偏差数组left[5][200],right[5][200],主要是用来保存N这个数在每个块里面小于N和大于N 5个的数,用来在后面读取
1。从文件里一个一个读取排序好的块,顺便把left,right两数组填充,找出<=N的数所在的index,最后把这些index相加为sum,看sum是否==1亿/2-1
如果相等了,那证明这个数就是中位数了,
2.如果小于
就又从left[0][200]里取最大的一个值,把left[0]排序一下,这样肯定是最接近N的,然后重复1,但是不改变left,right,看是否是中位数,
如果sum继续小于,那么继续2,但是要取left[1][200]最大了,如果sum这时候大于了,证明中位数肯定存在于left[0][200]其中的一个了,
这时候就锁定了,在left[0]用折半找按上面方法计算sum找中位数,
3。如果大于,和2步骤就是相反的。

这个算法虽然可以找到相关的值,但是在从文件重复读块加载到内存方面不知道读取了多少次,效率肯定不是一般的差,想了一两天,没思路了,哎。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
内存只能容纳100W个数,
现在有1亿数,混序,
然后求这一亿个数的中位数,
中位数(就是一个有序数组的中间数字,数组长度为偶数就是两个,奇数则只有一个)
  
/*****************************************************************************/
/* this program should find out the median(s) in N(logN)/(logB) no matter there
/* is duplicated data or not.
/*
/* with memory limitation: 4MB memory available.
/* I would like to express the idea with code.
/* here is just the pseudocode with out any optimization for easy understanding.
/* 
/* maybe, there is no need to check sum == N/2 or N/2+1, but this will get the 
/* median(s) as soon as possible with out more recursive invoking.
/*
/* sorry for any logical problem. please let me know if you found any.
/*****************************************************************************/
  
  
int N = 100000000;// total data number is N
int B = 1000000;  // number of buckets.
int min, max;
scan data from 0 to N-1 get min and max; // O(N);
  
void find_median(int num=0, int min, int max)
{
    if(min == max) {
        if(N%2) {
            print medians are min and max;
        }
        else print median is min; // show you the result
        return// exit
    }
  
    /* count all the data in O(N)*/
    int m = max-min > B ? (max-min) / B : 1;
    int cnt[B] = {0}; // count the data read.
    while(!EOF) {
        int data = read_data()-min;
        if(data >= min && data <= max) cnt[data/m]++;
    }
      
    int sum = num, median_1, median_2, i = 0;
    while(sum < N/2) sum += cnt[i++];
    i--; // median is in the range of [i*m, (i+1)*m-1]
  
    /* get median(s) when sum is N/2 */
    if(sum == N/2) {
        if(N%2) { // N is even and there are two medians.
            median_1 = (i+2)*m-1;
            median_2 = i*m;
            while(!EOF) {
                int data = read_data()-min;
                if(data/m == i) {
                    median_2 = (data > median_2 ? data : median_2);
                }
                if(data/m == i+1) {
                    median_1 = (data < median_1 ? data : median_1);
                }
            }
            pintf medians are median_1 and median_2;
            return;
        }
    }
    else // N is an odd number and there is one median.
        median_1 = (i+2)*m-1;
        while(!EOF) {
            int data = read_data();
            if(data/m == i+1) median_1 = (data < median_1 ? data : median_1);
        }
        print median is median_1;
        return;
    }
      
    /* get median(s) when sum is N/2+1 */
    if(sum == N/2+1) {
        if(N%2) { // N is even and there are two medians.
            median_1 = i*m;
            median_2 = i*m;
            while(!EOF) {
                int data = read_data();
                if(data/m == i) {
                    median_1 = max;
                    median_2 = (data > median_2 ? data : median_2);
                }
            }
            pintf medians are median_1 and median_2;
            return;
        }
    }
    else {
        median_2 = i*m; // get (N/2+1)th data.
        while(!EOF) {
            int data = read_data();
            if(data/m == i) median_2 = (data > median_2 ? data : median_2);
        }
        print median is median_2;
        return;
    }
  
    /* recursively to find out the median(s) */
    min = (i+1)*m-1;
    max = i*m;
    // get min and max for next processing
    while(!EOF) 
    {
        int data = read_data()-min;
        if(data/m == i)
        {
            min = (data < min ? data : min);
            max = (data > max ? data : max);
        }
    }
    find_median(sum, min, max);
}

算法,求1亿个数的中位数相关推荐

  1. 10 亿个数取中位数

    10 亿个数取中位数 1.取 16*1024 个数,生成一个 TreeMap .取得最大值 max 和最小值 min. 2.构造一个1024个元素的计数数组 T[i],对最初的 1024 个数按区间计 ...

  2. 【转】5亿个数找中位数

    原文链接:http://www.cnblogs.com/qianye/archive/2012/11/29/2794533.html 找中位数最容易想到的方法就是,先对序列进行排序,取中位数,然而5亿 ...

  3. 求几亿个数中不重复元素的个数

    题目: 有2.5亿个无符号整数(但在文件里面),要求找出这2.5亿个数字里面,不重复的数字的个数(那些只出现一次的数字的数目):另外,可用的内存限定为600M:要求算法高效.最优. 思路: 这么多个数 ...

  4. php算法求出一个数可以被分解成多少个_小学奥数必须掌握的30个知识模块汇总...

    关注成长教育  解决学习困惑 点击蓝字关注,与全国家长比肩同行 1.和差倍问题和差问题 和倍问题 差倍问题已知条件 几个数的和与差 几个数的和与倍数 几个数的差与倍数公式适用范围 已知两个数的和,差, ...

  5. php算法求出一个数可以被分解成多少个_最全的小学干货:34个数学重难点公式(三)...

    1.和差倍问题: 和差问题 和倍问题 差倍问题 已知条件 几个数的和与差 几个数的和与倍数 几个数的差与倍数 公式适用范围 已知两个数的和,差,倍数关系 公式 ①(和-差)÷2=较小数 较小数+差=较 ...

  6. php算法求出一个数可以被分解成多少个_小学数学必考的34个数学重难点公式,赶紧给孩子收藏!...

    34个小学数学重难点公式 1.和差倍问题 2.年龄问题的三个基本特征 ①两个人的年龄差是不变的: ②两个人的年龄是同时增加或者同时减少的: ③两个人的年龄的倍数是发生变化的: 3.归一问题的基本特点 ...

  7. php算法求出一个数可以被分解成多少个_程序员的算法趣题

    计算机的世界每天都在发生着深刻的变化.新操作系统的发布.CPU性能的提升.智能手机和平板电脑的流行.存储介质的变化.云的普及--这样的变化数不胜数. 在这样日新月异的时代中,"算法" ...

  8. php算法求出一个数可以被分解成多少个_面试时写不出排序算法?看这篇就够了(下)...

    昨天给大家介绍了面试时到底应该如何写出排序算法,也简单的介绍了一些方法 今天我们继续为大家介绍 前言 递归是一种解决问题的方法,它解决问题的各个小部分,直到解决最初的大问题.通常涉及函数调用自身. 能 ...

  9. 10亿个数中求最大的10个数字

    10亿个数中求最大的10个数字 应用场景 比如求10亿个数中的最大的前10个数,此时构建只有10个元素的小顶堆,如果比堆顶小,则不处理:如果比堆顶大,则替换堆顶,然后依次下沉到适当的位置. 比如求10 ...

最新文章

  1. ​纽约伊坎医学院房刚组诚聘博士后: 表观基因组, 宏基因组, 精准医疗
  2. ajax 请求svg,jQuery append 到AJAX加载的SVG问题
  3. JAVA入门级教学之(参数传递)
  4. windows下安装ta-lib的方法
  5. Mysql 5.5 编译参数
  6. C#看书笔记_02 核心C#
  7. 正则表达式替换字符串
  8. php 微信小程序签到功能,微信小程序每日签到
  9. 使用FeedDemon整理RSS Feed
  10. APP崩溃的主要原因
  11. html5捕鱼达人源码分享!!!
  12. 含类定义的完整python程序_含是什么意思 带含字的男孩名字 用含字起名的寓意...
  13. 零基础学习PS——#photoshop# 的167个技能!
  14. Zigbee入门指导(二)
  15. JSD-2204-API-线程并发-集合-Day08
  16. office2010安装包下载,专业版完整版官方原版
  17. rancher拉取harbor私有镜像失败,报错ImagePullBackOff: Back-off pulling image
  18. 比较好用的linux桌面系统,目前最好用的Linux桌面系统Mint
  19. 机械材料热处理工艺1(必备知识点)
  20. 思维导图帮助记忆,个人评估和辅助决策

热门文章

  1. C# 网络编程之豆瓣OAuth2.0认证详解和遇到的各种问题及解决
  2. 【数据结构与算法】之深入解析“H指数II”的求解思路与算法示例
  3. 11.2.3 事件
  4. 《信息学奥赛一本通》 高精除以低精。输入两个正整数,求它们的商(做整除)。
  5. 【机器视觉】 for算子
  6. 【ARM】ARM汇编程序设计(一)
  7. 【Linux】一步一步学Linux——hexdump命令(267)
  8. 【Linux】一步一步学Linux——ls命令(29)
  9. 用python语言实现-Python语言实现百度语音识别API的使用实例
  10. svpwm仿真_三相三线逆变_并网仿真建模