21. 合并两个有序链表
原始题目链接:https://leetcode-cn.com/problems/merge-two-sorted-lists/
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
解题思路:
有递归和迭代两种解法,递归的解法个人感觉不如二叉树的递归好理解,反而使用迭代法解决链表的问题更好理解。递归解法一定不要忘记三要素,递归函数定义,递归结束条件,递归等价关系式。递归法有一个地方就是返回值那里要注意,判断 l1 和 l2 头结点哪个更小,然后较小结点的 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, l1: ListNode, l2: ListNode) -> ListNode:
# 递归解法:递归三要素,递归函数定义,递归结束条件,递归等价关系式
# 递归函数定义:合并待排序的两个有序链表,参数是两个链表
# 递归结束条件:链表为空
# 递归等价关系:剩下未合并的两个有序链表
if l1 is None:
return l2
if l2 is None:
return l1
# 需要比较当前两个链表的待排序的节点大小
# 哪个节点小,哪个节点排在前面,将它的next指针指向剩下待排序的链表,此时就是递归调用
if l1.val <= l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
# 这个return一定不要忘记,l1的next指向剩下待排的链表(剩下的是下一层递归调用的事情)
# 那剩下待排的一定在最后会排好序,就是所以返回的就是下一层排好序的递归调用结果
# 再加上本层的l1.next,那就应该返回本层的结果,给调用本层的递归,就是上一层使用
# 就是需要返回l1
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
迭代法
# 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, l1: ListNode, l2: ListNode) -> ListNode:
# 申请一个节点,作用是最后直接返回它的next指针就是答案的头结点
dummy = ListNode(-1)
# 复制一个节点初始的时候指向dummy
cur = dummy
# 开始遍历并比较两个链表的节点的大小,并修改指向
# 循环结束条件是两个链表都有可比较的节点
while l1 and l2:
if l1.val <= l2.val:
# 当前节点的next指向较小的l1
cur.next = l1
# l1前移一个节点
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur = cur.next
# 此时将剩余的某个链表的其余节点放在cur的后面即可,因为链表都是有序的,不用再比较了
cur.next = l1 if l1 is not None else l2
return dummy.next
参考文献:
https://leetcode-cn.com/problems/merge-two-sorted-lists/solution/yi-kan-jiu-hui-yi-xie-jiu-fei-xiang-jie-di-gui-by-/
https://leetcode-cn.com/problems/merge-two-sorted-lists/solution/he-bing-liang-ge-you-xu-lian-biao-by-leetcode-solu/