这是一个面试问题。
宇宙中有数十亿颗恒星。您将使用哪种数据结构来回答查询 “给我最靠近地球的k星”。
我想到堆。正如我们可以在O(n)中进行堆化并在O(logn)中获得n_smallest一样。是否有更好的数据结构适合此目的?
答案 0 :(得分:1)
假设输入不能同时全部存储在内存中(这将是一个挑战!),而是宇宙中恒星的流-就像您将得到的迭代器之类的东西-您可以从使用最大堆(而不是首先想到的最小堆)中受益。
一开始,您只需要按堆中的星星(按它们与地球的距离来确定)即可,直到您的堆中有 k 个条目。
从那时起,如果新星的距离大于堆根的距离,则可以忽略它。当它比根星更近时,用新星代替根,然后对其进行筛选以恢复堆属性。
您的堆的增长不会超过 k 个元素,并且始终由您处理过的 k 个最近的恒星组成。
一些评论:
因为它是最大堆,所以您不知道哪颗是最近星(恒定时间)。当您停止该算法,然后一个接一个地拔出根节点时,您将得到按距离降序排列的 k 个最近的星星。
由于可观察的(!)宇宙估计有10 21 个恒星,因此您需要最好的超级计算机之一(1 exaFLOPS)来处理所有这些超级计算机。明星在合理的时间。但是至少该算法只需要在内存中保留 k 个星星即可。
答案 1 :(得分:0)
您要遇到的第一个问题是规模。仅银河系中就有约1000亿至4000亿颗恒星。估计有100亿个星系。如果我们假设每个星系平均有1000亿颗恒星,那么这就是宇宙中10 ^ 19颗恒星。您不太可能拥有该内存。即使您确实有足够的内存,也可能没有时间。假设您的heapify操作每秒可以进行十亿次迭代,则将花费一万亿秒(31,700年)。然后必须增加从堆中删除最小的k所需的时间。
通过使用多个线程或进程来构建堆,不太可能获得重大改进。
此处的关键是预处理数据并将其存储为一种形式,以便您快速消除大多数可能性。最简单的方法是按照与地球的距离排序列出恒星。因此,索尔(Sol)将在列表的顶部,普罗克西玛(Proxima Centauri)在其后,等等。然后,获取最近的k星将是O(k)运算:只需从列表中读取前k个项即可。
但是,排序后的列表很难更新。更好的选择是k-d tree。更新更加容易,并且与k个最近的邻居仍然相当快捷。