【问题标题】:How is the space complexity O(m+n) here?这里的空间复杂度 O(m+n) 如何?
【发布时间】:2020-05-30 19:46:48
【问题描述】:

合并两个已排序的链表并将其作为新链表返回。应该通过将前两个列表的节点拼接在一起来制作新列表。

class Solution:
    def mergeTwoLists(self, l1, l2):
        if l1 is None:
            return l2
        elif l2 is None:
            return l1
        elif l1.val < l2.val:
            l1.next = self.mergeTwoLists(l1.next, l2)
            return l1
        else:
            l2.next = self.mergeTwoLists(l1, l2.next)
            return l2

我知道这与堆栈有关。有人可以为我说清楚吗?我是新手,谢谢。

【问题讨论】:

    标签: python-3.x recursion linked-list space-complexity


    【解决方案1】:

    该算法的基本原理是每次递归调用都会从l1l2 中挑选一个元素。由于这只会发生M + N 次,因此时间复杂度将是O(M + N)

    空间复杂度是另一回事。

    我知道这与堆栈有关。

    是的。在 Python 中,递归调用需要每个递归级别的堆栈帧。堆栈帧保存调用参数和局部变量,以及允许调用返回到调用它的代码中正确位置所需的信息。

    在您的示例中,有M + N 级别,因此堆栈空间的空间复杂度为O(M + N)

    假设您的链表节点以一种明显的方式实现,您的合并方法正在改变 l1l2 对象,并且不再占用任何空间。


    许多语言/编译器支持称为尾调用优化的东西,用于递归调用自身的方法。如果可能,递归调用被优化为跳转到方法的开头,而不是使用调用指令。因此不需要堆栈帧。

    在您的示例中,堆栈使用的空间复杂度将是O(1)

    然而 Python 支持这个;见Does Python optimize tail recursion?

    【讨论】:

    • 所以每次调用递归函数时,所有变量都会在堆栈上创建?并且只有在函数返回后,堆栈才会被清除?我对么?我感到困惑的原因是因为我认为每个递归调用都在修改两个列表中的一个,这取决于哪个列表具有更大的第一个元素。 @斯蒂芬C
    • 你说的基本正确。但是堆栈没有“清除”。而是每次调用时都会将堆栈帧压入堆栈,并在调用返回时弹出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 2020-03-21
    • 1970-01-01
    • 2021-04-14
    • 2019-10-17
    • 1970-01-01
    相关资源
    最近更新 更多