【问题标题】:Which is better in finding minimum element Stack or Heap Data structure [closed]找到最小元素堆栈或堆数据结构哪个更好[关闭]
【发布时间】:2013-03-04 13:28:56
【问题描述】:

哪个更好,实现堆栈以获取最小元素或维护堆数据结构以提取最小元素。两者都给出了 O(1) 中的最小元素(如果您实现 2 个堆栈,一个具有最小元素,另一个堆栈具有实际输入)。

请解释一下,在什么情况下我们可以使用堆栈或堆来提取最小或最大元素以及为什么

【问题讨论】:

  • 你真的是说 Stack 吗?也许是树?
  • @Roman - 是堆栈。这在面试中经常被问到,面试官要求使用堆栈来实现。
  • 您是在问 system 栈和 system 堆进行内存分配,还是指使用栈和堆数据结构?跨度>
  • @mbeckish - 堆和堆栈数据结构 .. 很抱歉给您带来了困惑.. 我现在改变了我的问题。
  • 您可以扩充堆栈以在 O(1) 中为您提供最小值、最大值、几何/算术平均值等。只需将这些值与实际值一起存储并在每次 push() 时更新。

标签: algorithm data-structures stack heap


【解决方案1】:

我不太明白这个问题。

似乎类似于问题:我应该使用锤子还是水壶?答案是:目的是什么?

堆和栈的目的/行为是不同的

Heap 提供 API 类似:Insert(Key x), GetandDeleteMin()

虽然堆栈提供了 LIFO(后进先出)API:Push(Value x)、Value Pop()(如果需要,还有 GetMin())。

您应该问自己的问题是,我需要一个支持 min 的 LIFO 结构吗?如果是这样,您可以使用堆栈。

我是否需要一个“优先级结构”,我可以在其中以随机顺序插入,并删除具有最高/最低优先级的结构?如果是这样,您可以使用堆。

即您应该首先查看您需要的行为。

所有这些比较运行时间和空间使用情况的答案对我来说似乎也很奇怪。当用法本质上不同时,进行这种比较有什么意义呢?首先确定行为,然后如果您有选择,请进行时间/空间等比较。

你真正想要的是什么?

【讨论】:

  • 我的问题是在何时何地使用它们,我认为您通过查找行为然后选择数据结构来说明问题......谢谢
【解决方案2】:

MinHeaps 旨在快速为您提供最小元素。只需查看最小元素(不删除)就需要 O(1)(恒定)时间。通常,您将删除最小元素,这将迫使您重新堆化堆,这需要 log(n) 时间。 wikipedia article 绘图显示了 MaxHeap,但实现 MinHeap 几乎相同。

要在(单个)堆栈中找到最小元素需要 n 时间(并且 log(n) pop() 关闭每个元素,检查它是否小于你记住的最小值,然后将它 push() 到辅助堆栈上,直到你遍历整个堆栈。因此,如果获取最小元素是数据结构的主要目的,您通常会希望使用 MinHeap。

另一方面,其他人提到的两栈解决方案的操作(add、remove、getMin)复杂度为O(1),而removeMin的时间复杂度为O(n)。在最坏的情况下,它还需要 2N 空间。

总结一下:

              add/push 1    remove/pop 1   peekMin   removeMin   space
              ==========    ============   =======   =========   =====
one stack         O(1)          O(1)         O(n)       O(n)       n
two stacks        O(1)          O(1)         O(1)       O(n)      2n
minHeap         O(log(n)        N/A          O(1)     O(log n)     n

正如@rici 指出的 minHeap,支持 O(log n) 中的 removeMin 操作,即比堆栈更快,但是,对于 add/remove 和 peekMin,双堆栈解决方案更快。在“大于”和“小于”的关系之外,minHeap 也不维护顺序。

【讨论】:

  • “双栈”数据结构的 remove-min 操作为 O(n)。 pop() 与 remove-min 不同。
  • 是的,你是对的。我应该更加小心,并按运行时间按数据结构分解操作。谢谢!
【解决方案3】:

类似堆栈的数据结构[1] 和堆都支持“获取最小值”操作。 (请注意,我们讨论的是堆数据结构,而不是用于内存分配的“堆”。)它们都允许添加新元素。

它们在删除元素方面有所不同。具体来说,使用堆栈,您可以按照与插入相反的顺序删除元素。使用堆,您可以按值顺序删除元素(即始终删除最小值)。

所以你应该使用支持你需要的操作的那个。


[1] 所指的数据结构要么是两个并行的堆栈,要么是一对项目的堆栈;在这两种情况下,堆栈都会将添加的项目和最小值保持到该点,这可以在O(1) 中计算,因为它只是推送的项目的最小值和之前的最小值。

【讨论】:

  • 堆栈如何支持 O(1)“获取最小值”操作?您指的是 Roman 链接到的两个堆栈解决方案吗?
  • @mbeckish - 是的,通过维护 2 个堆栈,您可以支持 O(1)“获取最小值”操作
  • @mbeckish,是的,我应该更清楚地说明这一点。
  • @rici:如果堆被维护为一棵树,我们可以不删除 O(1) 中的最小值吗?我同意由于树指针而浪费了空间。
  • @user1952500:在一个堆中,我们可以去掉最小值,一般在O(log n)。但是很难删除“最后一个被推送的元素”。这就是我说的:“按顺序删除元素”
【解决方案4】:

你基本上可以使用a solution based on two stacks来找到最小值,但它并不有效(因为它消耗2 * N内存而堆消耗N内存)并且堆栈应该用于其他目的。

【讨论】:

  • 好吧,考虑到堆栈消耗的空间,这是有道理的。即使我们从堆栈中删除最小元素,堆的排序也会占用 O(nlogn),我猜这比维护 2 个堆栈要好
猜你喜欢
  • 2014-01-09
  • 2013-12-22
  • 1970-01-01
  • 2013-05-10
  • 2011-01-14
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多