8

我们有两个大小为 n 的数据库,其中包含没有重复的数字。所以,我们总共有 2n 个元素。它们可以通过一次查询一个数据库来访问。查询是这样的,您给它 ak 并返回该数据库中的第 k 个最小条目。我们需要在 O(log n) 查询的所有 2n 个元素中找到第 n 个最小的条目。

这个想法是使用分而治之,但我需要一些帮助来思考这个问题。谢谢!

4

3 回答 3

2

前不久在资格考试上看到了这个问题,闻起来像家庭作业的问题。因此,我只提出两个建议:

  • 研究二分搜索,仔细注意循环不变量的精确性质。Jon Bentley 的书Programming Pearls有一个很好的解释

  • 尝试推广二进制搜索的不变量。

  • 用各种特殊情况画一张图:

    • DB1 中的每个数字都小于 DB2 中的每个数字
    • 反之亦然
    • DB1 等于 DB2
    • DB2 中的每个数字都是 DB1 中相应数字的两倍

这是一个相当困难的问题;如果你直接去证明正确性,你会更容易。

于 2010-03-27T22:37:31.207 回答
1

尖端:

  • 观察你的“数据库”实际上是两个排序的数组。
  • 从数组的“中间”获取元素并进行比较。比较的结果可能允许您“排除”某些部分。
于 2010-03-28T01:28:41.853 回答
1

这就是我的想法。既然这是一个教育问题,我建议你停止阅读,如果有任何一点让你觉得,“啊哈,我没想到,我可以自己沿着这些思路进一步思考”。

1) 与 sdcwc 相同的观察结果:对于它是从 0 还是从 1 开始可能会有轻微的争论,数据库可以被认为是一个排序数组。我要求元素 0,我得到最小的。我要 12 个,我得到第 13 个最小的。等等。我发现这更容易可视化。

2) 我们知道我们正在寻找一个 O(log n) 算法。这意味着粗略地说,我们正在寻找以下两件事之一:

  • 我们要么从计算最小元素开始,然后计算第 2 小、第 4 小、第 8 等,直到达到我们想要的大小,每一步都在恒定时间内。这对我来说听起来并不乐观。

  • 或者我们从一个大小为 n 的问题开始,然后我们执行一些常数时间操作,这允许我们通过解决大小为 n/2 的问题来解决原始问题。显然我们可以在常数时间内求解n=1的问题,从而完成算法。这听起来更有道理。

实际上,不一定每次都必须是 n/2。它可能是 n/3 或 999*n/1000,结果仍然是 O(log n)。但是首先寻找 n/2 并没有什么坏处。

3)我们将如何减少这样的问题?好吧,如果我们可以从一个数组或另一个数组的开头打折/删除 m 个元素小于第 k 个最小的元素,那么我们可以找到结果数组对中第 (km) 个最小的元素,它将是原始数组中的第 k 个最小的。

4) 最后,突破性的观察是,如果数组 A 的第 m 个最小元素小于数组 B 的第 m 个最小元素,那么 A 的第 m 个元素不可能是两个数组组合中的第 (2m) 个最小元素。它小于那个(或相等的值:我不确定“无重复”是否意味着“每个数据库中没有重复”或“合并的数据库之间没有重复”),因为最多有 2*(m- 1) 两个数组组合中的元素严格小于它。

除非我犯了错误,否则剩下的就是编码。当 k 为奇数时,使用一个小的额外参数来解释 off-by-1,这个解决方案实际上是 O(log k),这是 O(log n),因为 k <= 2*n。

于 2010-03-28T11:07:47.083 回答