合并两个排序的链表

本文详细介绍了如何使用迭代和递归方法合并两个有序链表,并分析了它们的时间复杂度(O(n))和空间复杂度(迭代法O(1),递归法O(n))。同时提到了虚拟头节点在简化链表操作中的作用。
摘要由CSDN通过智能技术生成

核心:掌握如何连接两个有序链表

出错处:定义了新的链表,但是未想起来定义指针来为该链表添加节点

解决方法1-迭代法

对前序节点处理,之后处理剩余节点。

   def mergeTwoLists(self, l1, l2):
        p1 = l1
        p2 = l2
        dummy = ListNode(0) # Instantiate a new ListNode object as the head of the result list
        cur = dummy  # Use cur pointer to move and connect nodes
        
        while p1 is not None and p2 is not None:
            if p1.val > p2.val:
                cur.next = p2
                p2 = p2.next
            else:
                cur.next = p1
                p1 = p1.next
            cur = cur.next
        
        if p1 is not None:
            cur.next = p1
        if p2 is not None:
            cur.next = p2
        
        return dummy.next  # Return the next node of the head node, as the head node is empty


#Not using Pointers
def mergeTwoLists ( self , l1 , l2 )
        dummy = ListNode(0)
        cur = dummy
        
        while l1 and l2:
            if l1.val < l2.val:
                cur .next = ListNode(l1.val)
                l1 = l1.next
            else:
                cur . next = ListNode ( l2 . val )
                l2 = l2.next
            cur = cur .next
        
        cur.next = l1 or l2
        
        return dummy.next 

解决方法2-递归法

    def mergeTwoLists(self, l1, l2):
        if not l1:
            return l2
        if not l2:
            return l1
        
        if l1.val < l2.val:
            l1.next = self.mergeTwoLists(l1.next, l2)
            return l1
        else:
            l2.next = self.mergeTwoLists(l1, l2.next)
            return l2

复杂度

迭代方法:

  • 时间复杂度:O(n),其中 n 是两个链表中节点个数的总和。在最坏情况下,我们需要遍历完整的两个链表来完成合并。
  • 空间复杂度:O(1),迭代方法只需要常量级别的额外空间来存储一些指针变量,因此空间复杂度是常数级的。

递归方法:

  • 时间复杂度:O(n),其中 n 是两个链表中节点个数的总和。在最坏情况下,递归方法需要遍历完整的两个链表来完成合并,因此时间复杂度与迭代方法相同。
  • 空间复杂度:O(n),递归方法在执行过程中需要维护递归调用栈,其空间复杂度取决于递归调用的深度。在最坏情况下,如果链表较长,递归调用栈可能会达到 O(n) 的规模。

拓宽:虚拟头节点

当处理链表操作时,有时会使用虚拟头节点(dummy node)来简化操作。虚拟头节点是一个不存储实际数值的节点,它只是作为一个占位符存在,方便处理链表的插入和删除操作。

在合并两个有序链表、反转链表或者其他涉及头节点特殊处理的操作中,使用虚拟头节点可以大大简化代码逻辑,尤其是在涉及边界条件处理时。它可以有效避免单独处理头节点的情况,统一从虚拟头节点的下一个节点开始遍历整个链表。

在实际操作中,创建虚拟头节点的过程通常如下:

  1. 创建虚拟头节点,并将其初始化为空节点或者特定数值。
  2. 使用一个指针(通常命名为 cur)指向虚拟头节点,用来进行链表操作。
  3. 最终返回虚拟头节点的下一个节点作为操作的结果。

使用虚拟头节点能够使链表操作更加简洁和统一,避免了对头节点特殊情况的处理,同时也提高了代码的可读性和易维护性。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值