双端队列,其中所有 pushes/pops (front/back) 和 get_min() 都是 O(1) 操作

Deque in which all pushes/pops (front/back) and get_min() are O(1) operations

我只是想知道,是否有可能实现一个具有 O(1) 复杂度的结构 (list/deque) (const/amortized 无关紧要) 用于 get_min(), push_back(), push_front(), pop_back(), pop_front() 操作?

绝对有可能实现满足这些条件的stack or even queue(因为push()pop()只能用于一端)。但是我无法将此逻辑重新用于出队案例。

也可以创建具有 pushes/pops 复杂度 O(logn)get_min 复杂度 O(1) 的结构(只需使用简单列表和 min_heap可以删除 O(logn) 的任意元素。

但仍然摊销 O(1) 所有操作对我来说似乎是不可能的。如果是这种情况,关于操作的确切数量(或列表中元素的最大可能数量)n 的信息是否有帮助(更简单的情况)?我们能以某种方式使用 O(n)(或更多)额外的内存或类似这样的东西吗?

确实有可能构建一个 min-deque,其中 push-front、push-back 和 find-min 操作在 worst-case 时间内运行 O(1)而 pop-front 和 pop-back 操作需要分摊时间 O(1)。我知道最简单的路线是这样的:

  1. 首先,制作a stack that supports push, pop, and find-min in time O(1)。我们将以此为基础。
  2. 使用从三个堆栈构建双端队列的构造,除了使用这些 min-stacks 而不是常规堆栈。然后,您可以通过查询三个堆栈中的每一个堆栈的最小元素并返回这些值的最小值来实现 find-min 操作。

如果您还没有看到如何执行步骤 (2),这个想法是 how to make a queue from two stacks 的概括。您维护两个代表双端队列元素的堆栈,这样一个堆栈以相反的顺序代表双端队列的前端(栈顶是双端队列的前端,更深的元素是双端队列的下一个元素)和另一个的元素stack 代表双端队列的后面(顶部元素是双端队列的最后一个元素,更深的元素通过双端队列向后移动)。例如,这是对双端队列 1, 2, 3, ..., 10 进行编码的一种方法:

front: | 7 6 5 4 3 2 1
back:  | 8 9 10

要推送到双端队列的前端或后端,只需推送到适当的双端队列即可。要弹出双端队列的前端或后端,如果适当的堆栈是非空的,就从中弹出。否则,如果堆栈为空,则需要从另一个堆栈中移动一些元素。具体来说,为了保持两个堆栈之间的平衡,您进行一系列的压入和弹出操作,将一半的元素放入两个堆栈中的每一个。看起来像这样:

  1. 从另一个堆栈中弹出一半元素并将它们推入临时堆栈。
  2. 从另一个栈中弹出剩余的元素并将它们压入空栈。
  3. 从临时堆栈中弹出元素并将它们推回另一个堆栈。

您可以使用潜在参数(参见 Φ 是两个堆栈高度差的绝对值)证明每个操作都需要分摊时间 O(1)。

可以使用某种调度方案以某种方式将其速度提高到每个操作的 worst-case O(1) 时间,但我不确定如何执行此操作。我知道有一种方法可以用每个操作 worst-case O(1) 实现一个具有四个堆栈的队列,所以也许这个想法可以推广到这里工作?