【问题标题】:design a Queue that supports getMedian function设计一个支持getMedian函数的Queue
【发布时间】:2012-09-10 19:48:48
【问题描述】:

这是一道面试题。您需要设计一个包含整数值的队列,并具有一个 getMedian() 函数,该函数返回当前队列的中值元素。您可以使用 O(n) 额外空间。

getMedian()可以实现时间复杂度

例如: 当队列具有以下值时(2、1、2、2、6、4、2、5) 此方法返回 2 并且不会删除该对象。

【问题讨论】:

  • 对不起,我现在改了例子。
  • 队列是否有它可以包含的最大对象数?队列的所有其他功能(如推送和弹出)是否需要保持相同的复杂度?
  • 您必须尽可能高效地实现 getMedian。其他功能的复杂性不必保持不变。
  • 除非我弄错了,这是要求堆。
  • @user913359: 你想要队列 + 中位数,即先进先出,还是优先队列 + 中位数,即任意优先级最高的元素先出?

标签: algorithm data-structures


【解决方案1】:

您的问题的已知实现如下:

您需要实现的是 2 个堆,一个是最小堆,另一个是最大堆。
您还需要一个整数来告诉我们队列中的对象数量。

堆的约束如下:
1. 最小堆将拥有队列中较大的对象
2. 最大堆将包含队列中较小的对象
3. 最大堆的对象与最小堆相同或多 1 个

这样,如果您有奇数个对象,则中位数将恰好是您的最大堆中的最大对象。如果您有偶数个对象,则您的中位数将是堆的两个根的平均值(最大堆的最大值,最小堆的最小值)。

请务必注意,如果您的堆变得不均匀,例如,如果您要从某个堆中“弹出”,则需要从另一个堆中移除并移动它。但这不是问题,因为您需要处理的只是堆的根,仅此而已。

getMedian的时间复杂度变成O(1)

刚找到一篇关于这个主题的文章:link

回复评论

最大堆包含一半最小元素。
向队列中添加新数字时,首先检查队列中的对象数量。
如果要添加的数字是偶数,则意味着需要将其添加到最大堆中,因为两个队列的大小相同。
然后您会看到最大堆中的最大值是多少。
如果它大于你的数字,你可以将它插入到最大堆中。
如果它更小,则意味着您的新数字可能大于最小堆中的数字。
所以你会看到最小堆中的最小值是什么。
如果您的数字小于最小值,则可以将其插入最大堆中,如果更大,则将最小堆中的最小值移动到最大堆中,然后将新数字插入到最小堆中堆。
如果数字是奇数,则需要添加到最小堆,因为最大堆还有一个,依此类推..

它有点复杂,但如果你还是不明白,我不介意为你编写伪代码

【讨论】:

  • 如果队列有 n 个元素,那么 max-heap 的最大值大于至少 n/2 个元素(即 max-heap 中的元素)。但是你怎么能确定 min-heap 没有任何小于 max-heap 的元素,因为如果 max-heap 的 max 大于 min-heap 中的任何元素,那么我们有超过 n/2 个数字小于最大堆的最大值。如果我错了,请纠正我。
  • @Yarneo:这篇文章是关于 priority 队列的,而 OP 要求一个 queue。我知道你可以通过给第 i 个添加的元素优先级 i(或 -i,取决于你的优先级如何工作)来使用优先级队列来实现一个队列,但是如果我理解正确的话,这会破坏你的中值计算 - 你会得到具有中等优先级的元素,即队列中间的项目...
  • 嘿@ErikP。 ,谢谢你的评论。尽管如此,仍然存在队列,如果没有队列,您将不知道推送的元素的顺序。此问题中允许添加的 O(n) 空间是添加的 2 个额外堆,它们将 n 个对象累积在一起。所以这意味着我们将有 2 个相同的对象,一个在正常队列中,其行为与往常一样,另一个在其中一个堆中。
  • 我明白了 - 谢谢和 +1。我想了一秒钟,当一个元素被弹出时,从堆中删除元素会很慢,但我猜“传统”队列节点可能有指向相应堆节点的指针或引用,然后它很快。很好的解决方案!
猜你喜欢
  • 1970-01-01
  • 2011-04-21
  • 2010-11-20
  • 2023-03-04
  • 2018-03-25
  • 2021-01-22
  • 2018-12-20
  • 1970-01-01
相关资源
最近更新 更多