合并两个已排序的链表 - 理解为什么它是O(1)与O(N)空间复杂度

时间:2017-03-04 03:19:36

标签: data-structures merge linked-list big-o space-complexity

我看到的用于迭代合并两个已排序链接列表的大多数实现如下。

  

创建一个虚拟节点。将其指向具有较小值的链表头。将该头移动到下一个节点。将虚拟指针移动到下一个节点。重复。

我不明白为什么这个程序的空间复杂度为O(1)而不是O(N)?当我们将虚拟节点指向两个链接列表中的现有节点时,我们实际上创建了一个新的链表 - 一个交织两个现有列表的链表。因此,这还不需要O(N)空间吗?虚节点是其自己的链表的头部,它与原始的两个链表分开,即使它使用相同的节点...

2 个答案:

答案 0 :(得分:3)

你是完全正确的,你将需要Θ(n)存储空间来保存合并两个总长度n的列表的结果。但是在功能开始运行之前已经有多少存储空间存在,以及有多少存储空间是新的?你已经有两个n个元素的列表,所以你在开始使用这个算法之前就已经使用了Θ(n)空间了,当你完成后你就有了相同的列表,只是重新连接,以便下一个指针可能指向到不同的地方。因此,为此过程分配所需的内存量不是Θ(n),而是Θ(1)。

更一般地说,在测量空间复杂度时忽略问题输入使用的空间是很常见的,因为从某种意义上说,空间成本是不可避免的,你无法做任何事情来消除它。

未来的一条建议:如果你写的是O(1)或O(n)之类的东西,那么明确你是在测量时间或空间通常是一个好主意。例如,更清楚地说该过程需要 O(n)内存 O(1)时间而不是说过程“是”O(n)或“是”O(1),因为当你这样做时,你不清楚你用大O符号测量的是什么。

答案 1 :(得分:0)

要跟进templatetypedef的答案,因为输入和输出都使用相同的节点,所以没有额外的空间。

只有在不支持指针指针和/或简化代码的语言中才需要虚拟节点。在C / C ++的情况下,你可以使用这样的东西:

SessionDate