V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dwadewyp
V2EX  ›  算法

今晚上电面腾讯的一道算法题,求解

  •  
  •   dwadewyp · 2020-12-02 23:23:21 +08:00 · 3523 次点击
    这是一个创建于 1450 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有 1000 个.txt 文件,大小均为 1G,每个文件每行为一个浮点数; 要求: 将 1000 个文件中所有的浮点数按从小到大的顺序排好,放置在一个文件中;

    说思路

    19 条回复    2020-12-03 09:03:10 +08:00
    murmur
        1
    murmur  
       2020-12-02 23:44:30 +08:00
    如果是 utf-8 字符串表示的浮点数,那么如果全装进内存有没有可能加起来小于 1t,已知市面上比较好买的内存最大是单条 128g,这样一台 epyc 或者白金至强服务器带起 1t 内存就可以进行内存排序

    腾讯么,不差钱
    liukrystal
        2
    liukrystal  
       2020-12-02 23:53:27 +08:00 via iPhone
    个人提供一种思路,假设可用内存为 1G,那先对依次对每个 1G 文件内的浮点数进行快排,这样得到 1000 个已经排序的大小为 1G 的文件。然后依次扫描每个已经排序的文件,每个文件取出 1M 的内容,这样合起来大概是 1G,再对这些内容进行归并排序,结果写入硬盘,这样依次进行,其实是一种外排序的思路。
    jinhao7773
        3
    jinhao7773  
       2020-12-03 00:00:03 +08:00 via iPhone   ❤️ 7
    先对每个文件排序,再读取每个文件的第一行,对这 1000 个数字进行排序,把最小的那个数字进行 pop,再继续读取 pop 出来的数字的那个文件下一行放到那 1000 个数字里,继续 pop,如此循环,每次 pop 出来的数字写到输出文件里。
    iConnect
        4
    iConnect  
       2020-12-03 00:06:22 +08:00 via Android
    这个问题的结果会生成一个 1T 的 .txt 文件?
    across
        5
    across  
       2020-12-03 00:23:58 +08:00
    大概想一下,应该要先估算数量。
    float 32 位,最多 4294967296(2^32)个数字,建立一个 unint32 的数组(计数上限不能低于 2^32 ),这样内存占用 4294967296 * 4byte = 16G,这样就不用写出写入了。
    比较 float 时,直接进行位比较,想等的话对应位数字++,最后完成排序后可以,按对应数字输出一边····· 就好了? 细节实现可能有问题,IEEE 具体都忘了···
    across
        6
    across  
       2020-12-03 00:32:14 +08:00
    @across
    这样问题可以转化成,将所有 float 数字按顺序一边吧。
    Mohanson
        7
    Mohanson  
       2020-12-03 00:35:39 +08:00 via Android
    看题目就是外归并了,反正万能算法:不论大文件去重还是排序,答案都是外归并
    lithbitren
        8
    lithbitren  
       2020-12-03 01:31:16 +08:00
    外排序,一般标答都是纯归并,文件数不多的情况下也可以也可以基于堆做外排序的归并,1000 还是没问题的,嗯大概就是 3 楼那个意思,不过用堆比有序数组更正统,3 楼相当于插入排序了,复杂度还是有区别的。
    xupefei
        9
    xupefei  
       2020-12-03 01:40:20 +08:00
    @jinhao7773 你这方法复杂度爆表了,因为“对这 1000 个数字进行排序”重复了 n/1000 次。整体复杂度是 n^2 。
    wellsc
        10
    wellsc  
       2020-12-03 01:45:23 +08:00 via iPhone
    贱指 offer 貌似有这题
    fline
        11
    fline  
       2020-12-03 01:48:46 +08:00
    @xupefei 但整体不还是 nlogn 么……
    xupefei
        12
    xupefei  
       2020-12-03 02:41:43 +08:00
    @fline 就算 1000 个文件是排过序的,把他们 merge 起来已经是 nlogn 了。
    xupefei
        13
    xupefei  
       2020-12-03 02:46:27 +08:00
    @xupefei 仔细想了想,3L 如果是用最小堆进行 merge 的时候,最后的复杂度是 2*nlogn,的确是 nlogn 复杂度。
    binux
        14
    binux  
       2020-12-03 02:47:12 +08:00 via Android
    @xupefei 但是每次 pop add 一个是插入排序 logn 整体依旧是 nlogn
    yzbythesea
        15
    yzbythesea  
       2020-12-03 04:17:11 +08:00
    这不是经典的 merge sort 吗
    raaaaaar
        16
    raaaaaar  
       2020-12-03 07:24:52 +08:00 via Android
    昨天才看的排序,咋今天就有题了。典型的外排序,归并算法
    jinhao7773
        17
    jinhao7773  
       2020-12-03 07:28:38 +08:00 via iPhone
    @xupefei 1000 个数字只需要刚读出来的排一次就行,后面 pop 之后依然是有序的。
    rioshikelong121
        18
    rioshikelong121  
       2020-12-03 08:56:56 +08:00
    经典的外部排序问题。
    netnr
        19
    netnr  
       2020-12-03 09:03:10 +08:00 via Android
    把所有行写入数据库(sqlite ),排序导出,根据实际情况分批处理
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1871 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:22 · PVG 00:22 · LAX 08:22 · JFK 11:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.