目录
一、 小结 - 链表
参考文献:https://leetcode-cn.com/explore/learn/card/linked-list/197/conclusion/761/
二、合并两个有序链表
2.1 题目要求
2.2 实现过程
个人实现
法一:通过遍历左指针 left 和 右指针 right 将两链表合并到开辟的额外空间 —— 新链表 new 中。思想类似于合并两个有序数组。空间复杂度 O(n),时间复杂度 O(n)。
2020/07/11 - 34.56% - 次优方法
# 法一 - 基本版
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
new = ListNode() # 初始化结果链表
new_head = new # 结果链表哨兵节点
left = l1 # 左链表头节点
right = l2 # 右链表头节点
# 交替连接节点 - 元素从小到大
while (left and right):
new.next = ListNode() # 初始化下一个节点
new = new.next # 指向下一个节点
if left.val <= right.val:
new.val = left.val
left = left.next
else:
new.val = right.val
right = right.next
# 连接左链表剩余节点
while left:
new.next = ListNode()
new = new.next
new.val = left.val
left = left.next
# 连接右链表剩余节点
while right:
new.next = ListNode()
new = new.next
new.val = right.val
right = right.next
return new_head.next # 哨兵节点后的才是真头节点
法一改:将法一的重复代码块封装到函数 addNewNode() 中。
2020/07/11 - 34.56% - 次优方法
# 法一 - 优化版
class Solution:
def addNewNode(self, node, new):
""" 在结果链表指针 new 中加入节点 node """
new.next = ListNode()
new = new.next
new.val = node.val
node = node.next
return node, new
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
""" 创建一个新链表 new 以合并输入链表 """
new = ListNode() # 初始化结果链表
new_head = new # 结果链表哨兵节点指针
left = l1 # 左链表头节点指针
right = l2 # 右链表头节点指针
while (left and right): # 交替连接节点 - 元素从小到大
if left.val <= right.val:
left, new = self.addNewNode(left, new)
else:
right, new = self.addNewNode(right, new)
while left: # 连接左链表剩余节点
left, new = self.addNewNode(left, new)
while right: # 连接右链表剩余节点
right, new = self.addNewNode(right, new)
return new_head.next # 哨兵节点后的才是真头节点
# 错误记录
# 原先写了 addNewNode() 函数最后 return None, 且调用时没有接收返回值,
# 然后又改成 _ = self.addNewNode(right, new) (或 left) 等都是错误的
# 因为 right/left 和 new 都需要随着函数的调用而更新, 否则会陷入死循环
# 所有不仅要 addNewNode() 函数返回 right/left 和 new, 还要在调用处
# 接收和更新指针结果, 如 right, new = self.addNewNode(right, new)
官方实现与说明 (Nice)
# 果然还是递归法博大精深
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
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
# in-place 操作也很棒
class Solution:
def mergeTwoLists(self, l1, l2):
prehead = ListNode(-1) # 哨兵节点 - 伪头部
prev = prehead # 当前指针
while l1 and l2:
if l1.val <= l2.val:
prev.next = l1
l1 = l1.next
else:
prev.next = l2
l2 = l2.next
prev = prev.next
# 合并后 l1 和 l2 最多只有一个还未被合并完,
# 直接将链表末尾指向未合并完的链表即可
prev.next = l1 if l1 else l2
return prehead.next
参考文献
https://leetcode-cn.com/explore/learn/card/linked-list/197/conclusion/762/
三、两数相加
3.1 题目要求
3.2 解决过程
个人实现