在笔试中,我遇到了这样的问题:
当动态数组已满时,它将扩展到双倍空间,它就像2到4,16到32等。但是将元素放入数组的时间复杂度是多少?
我认为不应考虑扩展空间,所以我写了O(n)
,但我不确定。
答案是什么?
答案 0 :(得分:1)
这取决于被问到的问题。
如果问题要求插入一次所需的时间,那么答案是O(n),因为big-O意味着“最坏情况”。在最坏的情况下,您需要增长阵列。增长一个数组需要分配一个更大的内存块(正如你所说的那样经常是2倍大,但可能会使用大于1的其他因素),然后复制整个内容,这是现有的n个元素。在某些语言(如Java)中,还必须初始化额外的空间。
如果问题要求摊销时间,那么答案是O(1)。另一种说法是n加的成本是O(n)。
这怎么可能?每次加法是O(n),但是其中n也需要O(n)。这是摊销的美丽。为简单起见,假设数组从1开始,每次填充时增长2倍,因此我们总是复制2个元素的幂。这意味着第一次增长成本为1,第二次增长为2等。通常,增长到n个元素的总成本是TC = 1 + 2 + 4 + ... n。好吧,不难看出TC = 2n-1。例如。如果n = 8,则TC = 1 + 2 + 4 + 8 = 15 = 2 * 8-1。因此TC 与n 或O(n)成比例。
只要因子大于1,无论初始数组大小或增长因素如何,此分析都有效。
如果你的老师很好,他或她会以模棱两可的方式问这个问题,看看你是否可以讨论这两个答案。
答案 1 :(得分:0)
为了增加数组大小,你不能简单地在最后添加更多数据"因为你更有可能得到一个"分段错误"错误类型。因此,即使作为一个平均值,它需要θ(1)
个步骤因为你有足够的空间,如果O
符号是O(n)
,因为你必须将旧数组复制到一个新的更大的数组中(为此你分配了内存),这应该采取n
步骤...一般。另一方面,当然您可以更快地复制数组,因为它只是来自连续空间的内存副本,并且在最佳方案中应该是1步,即页面(OS)可以占用整个数组。最后......在数学上,即使考虑到我们正在制作n /(4096 * 2 ^ 10)(4 KB)步骤,它仍然意味着O(n)
复杂度。