程序员 第36章 10亿个数中找到最大的一个数以及最大的K个数 程序员 第36章 10亿个数中找到最大的一个数以及最大的K个数

15小时前

一、如何高效地找到最大的一个数

方法:将 10 亿个数据分成 1000 份,每份包含 100 万个数据,找到每份数据中的最大值。然后在这 1000 个最大值中再进行一次比较,找到最终的最大值。

优点:这种方法通过分割数据并行处理,能够有效减少单次操作的数据量,提高处理效率。每次处理的数据占用的内存较少,约为 4 MB,且总共需要进行 1000 次比较。

二、如何高效地找到第 K 大的数

方法:

对于 top K 问题,常用的方法是结合分治法、哈希、小顶堆等技术:

分治法:

  • 首先将数据集按照哈希方法分解成多个较小的数据集。

  • 对每个小数据集使用小顶堆找到其中最大的 K 个数。

  • 最后在所有数据集的 top K 结果中再次使用小顶堆找到全局的 top K。

小顶堆:

  • 构建一个大小为 K 的小顶堆,首先读入前 K 个数建立堆,然后遍历后续的数据,比较每个数与堆顶元素(最小的数)。

  • 如果当前数比堆顶元素大,则替换堆顶并调整堆结构,保持堆内始终是当前最大的 K 个数。

优点:

  • 时间复杂度:O(N log K)。其中,建堆的时间复杂度是 O(K),总的时间复杂度主要取决于遍历 N 个元素并调整堆的时间。

  • 适用场景:数据量大,数据分布广泛,通过分治可以有效减少内存使用,小顶堆确保了高效的 K 个最大数的计算。

三、top K 问题的常用方法

快排 + 选择排序:

  • 通过对整个集合进行排序后,直接查找第 K 个数。

  • 时间复杂度:O(N log N)。

  • 缺点:需要较大的内存,且整体排序的效率相对较低。

局部淘汰:

  • 先取前 K 个元素进行排序,然后扫描剩余元素,使用二分查找将新元素插入到已排序的 K 个元素中,并淘汰最小值。

  • 时间复杂度:O(N log K)。

Hash 法:

  • 对于重复率较高的数据,使用 Hash 方法去重,减少内存使用量,然后结合分治法或最小堆法查找 top K。

Trie 树:

  • 对于词频统计问题,通过 Trie 树统计词频,再结合小顶堆找出 top K。

  • 适用范围:数据量大,重复多,但种类小,能被内存容纳。

  • 时间复杂度:O(Len * N),其中 N 为字符串个数,Len 为字符串长度。

四、实际应用场景

单机+单核+足够大内存

  • 直接顺序遍历或使用HashMap计算词频,适用于内存能够容纳全部数据的情况。

单机+多核+足够大内存

  • 采用分区+多线程的方式,分配每个线程处理一个分区的数据,最后进行归并。

单机+单核+受限内存

  • 采用分治法,将数据分割成多个小文件,再依次加载到内存中处理。

多机+受限内存

  • 使用分布式处理,结合 MapReduce 框架,通过分发数据到多个机器并行计算。

五、总结

在处理 10 亿个数时,通过分治法结合小顶堆、Trie 树等方法,可以高效地找到最大的数或前 K 大的数。

这些方法既能充分利用内存和计算资源,又能应对大规模数据的挑战。

阅读 14

程序员文章
带到手机上看