

链表是逆序存储的(个位在头,高位在尾),这反而降低了难度,因为我们可以直接从头节点(个位)开始相加
运算符,名称,作用,在"两数相加"里的意义
- %,求余。当前位的结果( 0-9)
- //, 整除 ,进位 (Carry)
逻辑
同时遍历两个链表 l1 和 l2。
- 处理进位:相加时,每一位的和等于 v1 + v2 + carry(carry 为上一位的进位)
- 更新进位:当前位的值为 sum % 10,新的进位为 sum // 10。
哑节点:同样使用 ListNode(0) 作为哑节点来简化新链表的构建。
python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
prehead = ListNode(-1)
dummy = prehead
carry = 0 # 初始值,为了l1 or l2 or carry
# 只要 l1 有值,或 l2 有值,或还有进位没处理完,就继续循环
while l1 or l2 or carry:
# while or,,,即有可能链表已经空了
if l1:
v1 = l1.val
else:
v1 = 0 # 指向 null 时, 没有val ,则设置他是0
if l2:
v2 = l2.val
else:
v2 = 0
total = v1 + v2 + carry
mod = total % 10 # 求余数,在本位
carry = total // 10 # 整除,去进位
# 建立新节点并移动指针
dummy.next = ListNode(mod)
dummy = dummy.next
# 移动原链表指针
if l1:
l1 = l1.next
if l2:
l2 = l2.next
return prehead.next
移动原链表指针 和 建立新节点并移动指针 顺序随意
时间复杂度:O(max(m,n))
其中 m 和 n 分别为两个链表的长度。并行遍历两个链表,循环次数取决于较长的那个数。
空间复杂度:O ( 1 )
只额外使用了常数个指针变量(prehead 和 dummy)
- 在"两数相加"中:是并行前进的。每走一步,两个链表的指针同时向后移动。总步数取决于最长的那个。O(max(n,m))O(\max(n, m))O(max(n,m)):意味同时(并行)遍历 A 和 B
- 在"合并两个有序链表"中:是交替前进的。每走一步,只移动其中一个链表的指针(谁小移动谁)。O(n+m)O(n + m)O(n+m)