[LeetCode-Python版]21. 合并两个有序链表(迭代+递归两种解法)

发布于:2024-12-19 ⋅ 阅读:(14) ⋅ 点赞:(0)

题目

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:
在这里插入图片描述

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:
输入:l1 = [], l2 = []
输出:[]

示例 3:
输入:l1 = [], l2 = [0]
输出:[0]

提示:

  • 两个链表的节点数目范围是 [0, 50]
  • -100 <= Node.val <= 100
  • l1 和 l2 均按 非递减顺序 排列

题目链接

我的思路

  1. 处理空链表
  2. 设置一个头节点cur和最后用来返回的res,cur = res = ListNode(0)
  3. 用一个循环,当两个链表都不为空时,每次比较两个链表,将小的那个作为cur.next,同时它自己往后移,取自己的next
  4. 当有一个链表为空时退出循环,用两个判断来判断两个链表哪个不为空,将不为空的那个(如果有)接到cur后面
  5. 返回res.next,因为res是自己定义的头节点,它的next才是结果

我的代码

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        if not list1: return list2
        if not list2: return list1

        cur =  ListNode(0)
        res = cur

        while list1 and list2:
            if list1.val < list2.val:
                cur.next = list1
                list1 = list1.next
            else:
                cur.next = list2
                list2 = list2.next
            cur=cur.next
        
        if list1:
            cur.next = list1
        else:
            cur.next = list2
        
        return res.next
        

题解思路

题解还有另一种思路:递归

原问题可以转化成每次只比较两个节点的大小:

  • 如果list1的当前节点值小于list2的当前节点值,说明list1的当前节点应该在合并后的链表中排在前面。那么将list1的当前节点作为合并后链表的当前节点,然后递归地合并list1的下一个节点和整个list2,最后返回list1
  • 如果list2的当前节点值小于或等于list1的,那么将list2的当前节点作为合并后链表的当前节点,然后递归地合并list1和list2的下一个节点。最后返回list2

边界处理:

  • 当list1或list2为空时,返回不为空的那个作为链表的尾巴
    请添加图片描述

参考代码

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(
        self, list1: Optional[ListNode], list2: Optional[ListNode]
    ) -> Optional[ListNode]:
        if not list1:
            return list2
        if not list2:
            return list1

        if list1.val < list2.val:
            list1.next = self.mergeTwoLists(list1.next, list2)
            return list1

        list2.next = self.mergeTwoLists(list1, list2.next)
        return list2

Q&A

  1. 递归解法中为什么写 list1 = self.mergeTwoLists(list1.next, list2)会出错?
    • list1.next = self.mergeTwoLists(list1.next, list2)将list1的下一个节点(list1.next)替换为self.mergeTwoLists(list1.next, list2)的返回值,即合并list1.next和list2后的新链表的头节点。这样做保留了list1节点在原始链表中的位置,只是更新了它的next指针,指向了合并后的链表。
    • list1 = self.mergeTwoLists(list1.next, list2):将list1变量本身替换为self.mergeTwoLists(list1.next, list2)的返回值,即合并list1.next和list2后的新链表的头节点。这样做会导致list1变量失去了对原始链表中第一个节点的引用,因为变量被重新赋值了。这将导致原始的list1节点(如果它的值小于list2的头节点值)无法被正确地包含在合并后的链表中,因为递归函数返回时,无法追溯到这个节点。