给你两个 非空链表,每个节点存储一位数字,逆序排列,代表两个非负整数。
你要返回它们的和,结果也用链表表示,也是逆序排列。
✅ 题目保证:除了数字 0 以外,不会有前导零。
输入:
l1 = 2 -> 4 -> 3 (表示 342)
l2 = 5 -> 6 -> 4 (表示 465)
输出:
7 -> 0 -> 8 (表示 807)
其实就是模拟我们平时写的竖式加法:
链表是逆序的,其实是帮我们把“从低位到高位加”这件事搞定了,非常贴心。
public class ListNode {
public var val: Int
public var next: ListNode?
public init() { self.val = 0; self.next = nil; }
public init(_ val: Int) { self.val = val; self.next = nil; }
public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
}
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
let dummyHead = ListNode(0)
var p = l1, q = l2, current = dummyHead
var carry = 0
while p != nil || q != nil {
let x = p?.val ?? 0
let y = q?.val ?? 0
let sum = carry + x + y
carry = sum / 10
current.next = ListNode(sum % 10)
current = current.next!
if p != nil { p = p!.next }
if q != nil { q = q!.next }
}
if carry > 0 {
current.next = ListNode(carry)
}
return dummyHead.next
}
}
// 辅助方法:创建链表
func createLinkedList(_ numbers: [Int]) -> ListNode? {
let dummy = ListNode(0)
var current = dummy
for num in numbers {
current.next = ListNode(num)
current = current.next!
}
return dummy.next
}
// 辅助方法:打印链表
func printLinkedList(_ node: ListNode?) {
var current = node
var values: [String] = []
while current != nil {
values.append("\(current!.val)")
current = current!.next
}
print(values.joined(separator: " -> "))
}
// 调用示例
let l1 = createLinkedList([2, 4, 3])
let l2 = createLinkedList([5, 6, 4])
let solution = Solution()
let result = solution.addTwoNumbers(l1, l2)
printLinkedList(result) // 输出:7 -> 0 -> 8
步骤 | 操作 | 变量状态 | 结果链表 |
---|---|---|---|
1 | 初始化 | carry=0 | dummy → None |
2 | 第一次循环:2+5+0=7 | val1=2, val2=5, carry=0 | dummy → 7 |
3 | 第二次循环:4+6+0=10 | val1=4, val2=6, carry=1 | dummy → 7 → 0 |
4 | 第三次循环:3+4+1=8 | val1=3, val2=4, carry=0 | dummy → 7 → 0 → 8 |
5 | 循环结束,返回结果 | carry=0 | 最终结果:[7,0,8] |
时间复杂度:O(max(m, n))
空间复杂度:O(max(m, n))
1. 链表转整数
2. 相加
3. 整数转链表(逆序)
✅ 适用于“小数字”的投机取巧,但面试、比赛中不推荐。
知识点 | 说明 |
---|---|
链表遍历 | 两个链表一起遍历 |
处理进位 | 每次相加后都要考虑进位 |
虚拟头节点 | 让链表插入操作更方便 |
链表节点为 nil 时当 0 处理 | 避免越界 |
时间 & 空间复杂度 | O(max(m, n)) |
这道题,其实就是「模拟手算加法」+「链表遍历」的结合。逆序排列正好符合我们从低位加起的习惯,代码写出来一看就明白!