【问题标题】:Implementing Deque using 3 Stacks (Amortized time O(1))使用 3 个堆栈实现 Deque(摊销时间 O(1))
【发布时间】:2014-06-28 10:16:15
【问题描述】:

我有一个关于如何工作的问题:

使用 3 个堆栈实现双端队列。 Deque 有这些操作:InsertHead、InsertTail、DeleteHead、DeleteTail。证明每个操作的摊销时间为 O(1)。

我尝试将问题视为河内问题。 所以让我们将堆栈称为:L(左),M(中),R(右)。

伪代码实现:

InsertHead(e):
     L.push(e);

DeleteHead(e):
     L is empty:

       while R is not empty:
          pop and insert the element to M;
       pop M;
       while M is not empty:
         pop and insert the element to R;

     L is not empty:    
       L.pop(e);

InsertTail 和 DeleteTail 与上述实现原理相同。 如何证明摊销时间为 O(1)? 因为 L 中可以有 N 个元素,并且 wile 循环需要 O(n),现在如果我调用 deleteHead N 次来计算摊销时间,复杂度不会是 O(n^2)?

有人可以帮助我如何证明上述实现在摊销时间内需要 O(1)?

【问题讨论】:

  • 使用两个堆栈:L 和 R。当尝试在空 L 上弹出(L)时,将 R 中的所有元素平均分配给 L 和 R(此操作需要第三个堆栈)。
  • 为什么将 R 在 L 和 R 之间平分,而不是像我一样?
  • 因为这样你不会得到 O(1) (如果 L 总是为空会发生什么?)
  • 好的,假设我知道 R 中的元素数量是多少,我使用第三个堆栈将它平分在 L 和 R 之间(根据问题要求)所以如果我在 R 中有 N 个元素, 仍然.. 我需要遍历 R 中的 N 个元素,以平均划分 L 和 M 之间的元素,然后我需要移动 M 的元素以将它们转移回 R。对吗?现在,如果我尝试调用 DeleteHead N 次,它仍然是 O(n^2)。那么摊销时间怎么可能是 O(1)?!
  • Egor 和 n.m 我已经编辑了我的问题并添加了一张描述您的解决方案的图片。它怎么可能是 o(1)?

标签: algorithm data-structures stack deque amortized-analysis


【解决方案1】:

我们继续使用potential method;定义

Phi = C |L.size - R.size|

对于一些常量C,我们稍后会为其选择一个值。让Phi_t 表示t 操作后的电位。请注意,在两个堆栈大小相等的“平衡”状态下,数据结构的电位为 0。

任何时候的势都是常数乘以每个堆栈中元素数量的差异。请注意Phi_0 = 0,因此在初始化结构时电位为零。

很明显,push 操作最多会增加C 的潜力。不会错过的弹出操作(即相关堆栈非空)也最多将电位改变C。这两个操作的真实成本为 1,因此它们的摊销成本为 1 + C

当弹出操作发生并导致 miss(当我们要弹出的堆栈为空时),操作的真正成本是1 + 3/2 * R.size,因为我们试图从中弹出L,当我们从 R 弹出时反之亦然。这是因为我们将 R 的一半元素移到 M 并移回,并将 R 的另一半元素移到 L。+1 是必需的,因为在此重新平衡操作完成后从 L 最终弹出。

因此如果我们取C := 3/2,那么发生miss时的pop操作的摊销成本为1,因为由于再平衡,潜力从3/2 * R.size减少到0,然后我们可以重新平衡后发生的 pop 会产生额外的 3/2 成本。

换句话说,每个操作都有一个由常数限制的摊销成本。

最后,由于初始电位为0,且电位始终为非负数,因此每次操作的摊销成本为O(1),按要求进行。

【讨论】:

    猜你喜欢
    • 2010-10-12
    • 2019-05-09
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 2013-10-30
    • 2021-06-02
    • 1970-01-01
    • 2011-05-04
    相关资源
    最近更新 更多