【发布时间】:2015-02-10 09:55:20
【问题描述】:
最近去面试,面试官问了我这个问题。
有 k+1 堆大小1, 2^1, 2^2, 2^3, ...,2^k。让我们分别称他们为stack 1, stack 2, ... stack k+1。当insert(x) 被调用时,元素被插入到第一个堆栈,即大小为 1 的堆栈。如果该堆栈已满,则该堆栈的元素被移动到下一个堆栈,然后元素被插入第一个堆栈。它类似于管道操作。堆栈 1 将元素推入堆栈 2,堆栈 2 推入堆栈 3,依此类推。如果所有堆栈都已满,那么我们会抛出一个错误,说明堆栈溢出。还有另一个操作,delete(x)。它从堆栈堆栈中删除 x。因此,如果 x 不是最顶部的元素,即它不存在于堆栈 1 中,则我们从中弹出元素,然后移动元素,然后再次尝试弹出,直到找到该元素并将其删除。此实现的插入和删除的摊销复杂度是多少?
编辑 1:展示插入和删除的工作原理。
假设有 2 个堆栈,堆栈 1 和堆栈 2 的大小分别为 2^0 和 2^1。
迭代 0:堆栈 1 -> {},堆栈 2 -> {}迭代 1:插入 (1)。堆栈 1 -> {1},堆栈 2 -> {},顶部 -> 1
迭代 2:插入 (2)。堆栈 1 -> {2},堆栈 2 -> {1},顶部 -> 2
迭代 3:插入 (3)。堆栈 1 -> {3},堆栈 2 -> {2,1},顶部 -> 3
迭代 4:插入 (4)。溢出异常。堆栈 1 -> {3},堆栈 2 -> {2,1},顶部 -> 3
迭代 5:删除 (2)。
- 我们弹出 3,因为 2!=3 并继续。堆栈 1 -> {2},堆栈 2 -> {1},顶部 -> 2
- 我们弹出 2 并返回。堆栈 1 -> {1},堆栈 2 -> {},顶部 -> 1
迭代 6:插入 (4)。堆栈 1 -> {4},堆栈 2 -> {1},顶部 -> 3
希望这两个操作现在都清楚了:)
我尽了最大努力,只能说出最坏情况的时间复杂度,即1+2^1+2^2+..+2^k(几何级数总和)。我不是在寻找最坏情况的时间复杂度。我什至无法达到摊销的复杂性。谁能帮助理解如何计算这个问题的摊销复杂度?
【问题讨论】:
-
如果您不立即知道
1+2^1+2^2+..+2^k的总和是什么,您可能需要进一步研究。无论如何,尚不清楚当堆栈已满时元素如何移动。您是将它们全部移到下一个堆栈上,还是只移动一个? -
考虑:在你插入一个导致你转储堆栈
n的元素之后,它下面的所有堆栈必须是什么样子?你多久转储一次堆栈n?因此,分配给堆栈n的每次插入摊销成本是多少? -
@n.m.我知道如何解决几何和!请正确阅读问题。我要求的是渐近复杂度,但不是最差的时间复杂度!!该总和导致最坏情况的时间复杂度。无论如何,我们将所有元素一个接一个地移动(类似于在给定索引中插入数组中的元素会导致所有元素移动)。
-
@Sneftel 转储堆栈 n 是什么意思?我们不会删除任何堆栈,如果所有堆栈都已满,那么我们会抛出错误消息。编辑问题以显示插入将如何进行。
-
啊,好的。我懂了。因此,当您在 (k+1) 个堆栈中插入 N=((2^k+1)-1) 个元素时,1 个元素根本没有移动,2 个元素移动了 1 个位置,4 个元素移动了 2 个位置, ...,并且 2^k 个元素移动了 k 个位置。因此,您需要找到总和
0*1 + 1*2 + 2*4 + 3*8 + ... k*2^k,然后将其除以 (2^(k+1)-1) 以获得每个元素的操作数。这小于 k,但大于 k/2(实际上它几乎正好是 k-1),因此渐近摊销复杂度为 O(log N)。
标签: algorithm time-complexity amortized-analysis