百度的一个面试题:从 1 亿个无序数据里找第 5000W 个 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
a1310747
V2EX    问与答

百度的一个面试题:从 1 亿个无序数据里找第 5000W 个

  •  
  •   a1310747 2017-02-28 16:44:35 +08:00 8433 次点击
    这是一个创建于 3151 天前的主题,其中的信息可能已经有所发展或是发生改变。

    具体该如何实现,我完全没头绪 只能想先排序然后找

    32 条回复    2017-03-01 22:30:45 +08:00
    msg7086
        1
    msg7086  
       2017-02-28 16:45:50 +08:00
    a[5000w]?

    你是想说排大小排第 5000w 的那个?
    xxdd
        2
    xxdd  
       2017-02-28 16:50:53 +08:00
    select t.numbe from table t order by t.number limit 50000000,50000000

    简单 粗暴!速度慢 加内存 加索引
    msg7086
        3
    msg7086  
       2017-02-28 16:54:02 +08:00
    要我做的话,小顶堆或者半个快排。
    exoticknight
        4
    exoticknight  
       2017-02-28 17:00:24 +08:00
    感觉像编程珠玑里面的一题?
    neosfung
        5
    neosfung  
       2017-02-28 17:06:53 +08:00
    morefreeze
        6
    morefreeze  
       2017-02-28 17:07:30 +08:00   3
    就是快排分组那个算法改一下,每次只用去其中一半找就行了,记得复杂度平均下来是 N
    Valyrian
        7
    Valyrian  
       2017-02-28 17:09:49 +08:00
    无序数组找中位数是经典面试题啊= =
    https://en.wikipedia.org/wiki/Median_of_medians
    srlp
        8
    srlp  
       2017-02-28 17:14:23 +08:00 via iPhone
    这是算法题吧,可以考虑快排或者最小堆。
    2lecl
        9
    2lecl  
       2017-02-28 17:16:20 +08:00
    可以反问一下面试官,数的分布情况
    如果分布均匀,就 mapreduce
    a1310747
        10
    a1310747  
    OP
       2017-02-28 17:33:20 +08:00
    最近面试被打击的不行...
    ninjadq
        11
    ninjadq  
       2017-02-28 17:40:22 +08:00   1
    先用 O(n)的 shuffle 算法打散,然后用快排的 partition 操作一步步逼近
    kindjeff
        12
    kindjeff  
       2017-02-28 17:41:39 +08:00
    是什么数据?如果是数值类型的话,我有一个思路不知道行不行。

    把 1 亿个数遍历一遍,找到数值的范围(最大值和最小值),比如是 0 到 100 亿。
    然后把它分成 10 万个区间,第一个区间代表数值是在 0 到 10 万,第二个区间是 10 万零 1 到 20 万以此类推。然后像桶排序那样,把这 1 亿个数遍历一遍并放入数值所在的区间。然后就可以知道每个区间的数值个数,然后直接可以定位到一个区间。

    然后以此类推。
    binux
        13
    binux  
       2017-02-28 17:46:54 +08:00
    百度拿这个问题问了 10 年了吧
    lishunan246
        14
    lishunan246  
       2017-02-28 18:33:34 +08:00
    quick select
    danielmiao
        15
    danielmiao  
       2017-02-28 19:35:04 +08:00
    @neosfung 这个文章我看了,关于分治法的一个疑问,一个大文件取出现概率前 100 的数,就是吧一个大文件分成 N 份以后取每个文件的前 100 ,再归并排序,但是为什么整个文件的前 100 的数一定在这 N 份文件的 TOP100 里面??会不会出现一个数是每个文件的 TOP101 ,但是整个文件里面是 TOP100 内的?
    h3nng
        16
    h3nng  
       2017-02-28 19:57:07 +08:00
    @binux 233 ,我当年面试也是这个问题。。
    a1310747
        17
    a1310747  
    OP
       2017-02-28 20:17:07 +08:00
    @h3nng 你是怎么回答的呢
    snnn
        18
    snnn  
       2017-02-28 20:54:24 +08:00 via Android
    方法有很多种,我告诉你一个一般人不知道的:区间估计。先采样,然后做区间估计。然后拿这个区间去筛原始的 input 。然后随便怎么搞都行。
    billlee
        19
    billlee  
       2017-02-28 21:07:21 +08:00
    半边的快排,复杂度 O(n), 这不是基础算法吗?
    neosfung
        20
    neosfung  
       2017-02-28 22:43:31 +08:00
    @danielmiao 你可能理解错我的分治法的意思了
    假设是 INT32 的类型,你就建个大小为 2^32 的 array
    遍历原始数据,每个数在 array 相对应的位置加一
    然后遍历 array ,就知道 5000W 是哪个数了
    内存不能够建 2^32 大小的数组?没关系,你可以建个 2^16 大小的数组,每个元素是个指针,指向一个 2^16 大小的数组。然后每个数据可以切分为前后两部分。
    百度问你这条题,是因为还有 follow up 的问题的
    就是如果这些数据都不能一次放到内存里面呢?如果这些数据都分散在很多台机器上呢。
    都可以用我提到的方法通过外存来解决
    roychan
        21
    roychan  
       2017-02-28 22:46:57 +08:00
    Median of medians … O(n)
    neosfung
        22
    neosfung  
       2017-02-28 22:50:23 +08:00
    @danielmiao 不好意思,以为你是题主,我搞错了,回复的是题主的问题,不是你的问题。
    neosfung
        23
    neosfung  
       2017-02-28 22:54:31 +08:00   1
    @danielmiao 关于你这个问题,是肯定存在的。所以这个文章后面就提到了解决方法 “因此不能将数据随便均分到不同机子上,而是要根据 hash 后的值将它们映射到不同的机子上处理,让不同的机器处理一个数值范围。”
    ic2y
        24
    ic2y  
       2017-02-28 22:55:28 +08:00   1
    1 亿数字是 4GB 内存,可以直接加载进内存

    对 快速排序做点改动,就能实现。

    快排第一趟分治结束的时候,会以一个数字为轴,左边小于这个数字,右边大于这个数字,而且这个轴的下标是知道的。

    如果下标等于 5000w ,那就直接买命中,如果下标小于 5000w ,对右半部进行快排的第二趟快排。如果大于 5000w ,对左半部进行快排的第二趟。

    以此类推,得出 5000w 的是几。
    danielmiao
        25
    danielmiao  
       2017-02-28 23:16:41 +08:00
    @neosfung 感觉自己突然傻 B 了。。。。
    mystzain
        26
    mystzain  
       2017-03-01 01:25:09 +08:00
    先对前面 N 条数据采样,分析一下分部规律,然后决定一个策略,分成多个区间,然后从原始数据那边取值分拣到多个区间里面,统计各个区间内的条目数。决定对哪个区间进行进一步的分拣或者排序。这样行吗……?
    eyp82
        27
    eyp82  
       2017-03-01 03:59:03 +08:00   1
    建议别这么急着就解题, 要先问一下详细情况, 暂时想到一些:
    1. 数据类型
    2. 每条数据的长度范围, 长度分布情况(最好给个 histogram)
    3. 全部数据的排序情况, 是基本有序, 还是乱序
    4. 对性能 /延迟和资源占用的要求(性能高延迟低的, 资源占用可能会很大, 合理取舍)
    5. 内存大小(是否能全部加载到内存)
    6. 解决这个问题的时间要求.(要求在多长时间内搞定之类)
    7. 可能还要考虑这个算法的可靠性要求(比如要求可靠性几个 9)

    根据具体的情况, 才能选择合适的算法.

    这只是问题本身, 如果考虑的更全面一点, 在问上述的问题前后, 还要问的是具体的也无需求, 是否真的需要这个场景, 还是可以用逻辑上等价的其他成本更小的操作代替?
    mcfog
        28
    mcfog  
       2017-03-01 08:15:15 +08:00 via Android
    当年面试唯一答不出来的就是类似的排序算法变形题,面试官都想往我脸上甩堆排序三个大字了,我愣是想不起来只能疯狂聊如何优化快排…

    不管怎么说,只能想到先排完序的话,算法没学好(或者说学成背公式了)
    graycreate
        29
    graycreate  
       2017-03-01 08:20:57 +08:00 via iPhone
    m
    vanquish70
        30
    vanquish70  
       2017-03-01 08:35:38 +08:00
    二分法
    ljcarsenal
        31
    ljcarsenal  
       2017-03-01 11:44:50 +08:00 via Android
    mark
    wohenyingyu02
        32
    wohenyingyu02  
       2017-03-01 22:30:45 +08:00
    既然是无序数组,直接随便取一个在 iterator 中把它定义成第 5000w 个不就行了吗?谁规定必须要从第一个开始遍历?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5556 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 06:32 PVG 14:32 LAX 23:32 JFK 02:32
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86