【问题标题】:The kth smallest number in two arrays, one sorted the other unsorted两个数组中第 k 个最小的数,一个已排序,另一个未排序
【发布时间】:2019-05-07 09:27:27
【问题描述】:

已经有一个answer 用于两个排序数组。但是,在我的问题中,其中一个数组未排序。

假设X[1..n]Y[1..m] 其中n < m。 X 已排序,Y 未排序。找到X U Y的第k个最小数的有效算法是什么。

MinHeap 可用于在未排序的数组中找到第 k 个最小的数。但是,这里对这些数组之一进行了排序。我能想到:

 1. Building a `MinHeap` for `Y`
 2. i = 1, j = 1
 3. x1 = extract Min from Y
 4. x2 = X[i]; 
 5. if j == k: return min(x1, x2)
 5. if x1 < x2: j++; goto 3
 6. else: j++; i++; goto 4 

它是否有效且正确?

【问题讨论】:

  • 在为“Y”构建最小堆时,您已经涵盖了 O(m log m) 复杂度。那么,为什么不对“Y”进行排序并应用与两个排序数组相同的方法!!
  • 我认为从 Y 构建堆就像对 Y 排序一样。构建堆的顺序是什么?从 Y 中提取 Min 的顺序是什么?
  • @MahmoudHanafy 用m 构建一个堆是O(m)。从中提取最小的东西是O(log(m))。按排序顺序提取所有内容是O(m log(m))。你可以在这个问题上做得更好。
  • @BishalGautam 从Y 构建堆是 O(m),而不是 O(m log m)。参见例如stackoverflow.com/questions/1787252/…

标签: arrays algorithm min


【解决方案1】:

没有任何帮助,但您必须扫描Y。这需要O(m),所以你不能比O(m)做得更好。

但是quickselect 的性能平均O(m)。基本上,该算法只是进行快速排序,除了您忽略所有没有最终答案的分区。

鉴于n &lt; m,我们可以简单地将一个数组连接到另一个数组并进行快速选择。

请注意,平均性能很好,但最坏情况下的性能是二次的。为了解决这个问题,如果您没有足够快地取得进展,您可以切换到相同的中位数算法,该算法可以保证快速排序的性能(尽管常量不好)。如果您不熟悉它,那就是将数组分成 5 个组,找到每个组的中位数,然后重复直到减少到 1 个元素。然后将该元素用作整个数组的基准。

【讨论】:

  • 谢谢,什么是理论上最好的(最坏的情况)
  • @Ahmad 如果您每隔 5 次运行中位数的中位数,那么您的平均情况不会受到太大影响,而最坏的情况仍然是 O(m)。所以我建议这样做。
【解决方案2】:

从已排序的数组 (X) 中创建最小 k 个项目的最大堆。这需要 O(k) 时间。

对于未排序数组 (Y) 中的每个项目,如果它小于堆中最大的项目(根),则从堆中删除根并添加新项目。最坏的情况是 O(m log k)。

完成后,第 k 个最小的数字将位于堆的顶部。

虽然第二部分的最坏情况是 O(m log k),但平均情况要好得多,因为通常必须将一小部分项目插入堆中。

【讨论】:

    猜你喜欢
    • 2020-09-12
    • 1970-01-01
    • 2017-03-04
    • 1970-01-01
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    相关资源
    最近更新 更多