

文章目录
摘要
这道题是经典链表加法的"升级版"。和普通相加不同的是:
- 数字是"从高位到低位"存储的(反着来)。
- 输入链表不能被翻转(进阶要求)。
因此不能直接像 LeetCode 2 那样从头开始相加,只能想办法把最高位的数字放到最后进行计算。
最常见的做法是:
- 把两个链表的值分别压入两个栈
- 从栈顶开始做加法(栈顶就是最低位)
- 边算边构建新链表(头插法)
这种写法特别清晰,也符合进阶要求。

描述
我们要处理两个非空链表,每个节点只存储一位数字,而且链表从头到尾是从"最高位 → 最低位"。
举个例子:
txt
7 → 2 → 4 → 3
代表的数字是 7243
另一个:
txt
5 → 6 → 4
代表的是 564
两者相加:
txt
7243 + 564 = 7807
得到:
txt
7 → 8 → 0 → 7
链表顺序不能反转,也不能存成数组再反转,所以需要用栈来处理。
题解答案
核心思路:
- 遍历两个链表,把值分别压入两个栈。
- 栈顶的元素就是最低位,所以我们从栈顶开始相加。
- 进位正常处理。
- 每次计算结果后创建新节点,并将该节点插入链表头部。
- 遍历结束后返回头节点。
这类问题在工程里其实很常见,比如:
- 处理日志编号:左边是高位,右边是低位,需要从右边开始加
- 做大整数运算:避免翻转原始结构
- 流式处理数字时需要用先入后出的方式处理高位数据
链表 + 栈的组合非常优雅。

题解代码分析(附可运行 Swift Demo)
下面这段 Swift 代码可以直接运行。
swift
import Foundation
public class ListNode {
public var val: Int
public var next: ListNode?
public init(_ val: Int) {
self.val = val
self.next = nil
}
}
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
var stack1 = [Int]()
var stack2 = [Int]()
// 把链表值压入栈
var p = l1
while p != nil {
stack1.append(p!.val)
p = p!.next
}
var q = l2
while q != nil {
stack2.append(q!.val)
q = q!.next
}
var carry = 0
var head: ListNode? = nil
// 两个栈都空且没有进位时才能结束
while !stack1.isEmpty || !stack2.isEmpty || carry > 0 {
let x = stack1.popLast() ?? 0
let y = stack2.popLast() ?? 0
let sum = x + y + carry
carry = sum / 10
let node = ListNode(sum % 10)
// 头插法,把当前结果挂到前面
node.next = head
head = node
}
return head
}
}
// MARK: - Demo 测试
func buildList(_ arr: [Int]) -> ListNode? {
let dummy = ListNode(0)
var cur = dummy
for num in arr {
cur.next = ListNode(num)
cur = cur.next!
}
return dummy.next
}
func printList(_ head: ListNode?) {
var p = head
var res = [Int]()
while p != nil {
res.append(p!.val)
p = p!.next
}
print(res)
}
func runDemo() {
let sol = Solution()
let l1 = buildList([7,2,4,3])
let l2 = buildList([5,6,4])
let ans1 = sol.addTwoNumbers(l1, l2)
print("示例 1 输出:", terminator: "")
printList(ans1)
let l3 = buildList([2,4,3])
let l4 = buildList([5,6,4])
print("示例 2 输出:", terminator: "")
printList(sol.addTwoNumbers(l3, l4))
let l5 = buildList([0])
let l6 = buildList([0])
print("示例 3 输出:", terminator: "")
printList(sol.addTwoNumbers(l5, l6))
}
runDemo()
示例测试及结果
下面是 Demo 输出的结果:
示例 1
txt
输入: [7,2,4,3] + [5,6,4]
输出: [7,8,0,7]
符合预期的 7807。
示例 2
txt
输入: [2,4,3] + [5,6,4]
输出: [8,0,7]
因为 243 + 564 = 807。
示例 3
txt
输入: [0] + [0]
输出: [0]
最简单的情况。
与实际场景关联
这个题型在真实业务中非常有用,尤其是处理数字从高位到低位排列的数据结构时,例如:
1. 构建银行流水号或订单 ID
有些系统会把订单号拆成链式结构,按高位存储,这时候加法操作不能破坏原始顺序。
2. 事件流中的时间戳分段存储
日志系统可能会按层级分段存储时间戳,高位年份在前,低位毫秒在后,需要从后往前加。
3. 大数运算引擎实现
大数库需要支持不可逆结构,不能频繁翻转内部结构,这种题的解法就非常适用。
时间复杂度
遍历两个链表压栈:
O(n + m)
相加过程又是一次遍历两个栈:
O(n + m)
整体:
O(n + m)
空间复杂度
使用两个栈保存链表值:
O(n + m)
返回链表占用的空间不算额外空间(题意如此)。
总结
这道题用链表直接相加会很麻烦,用"两个栈"来倒置链表顺序,是最自然且满足进阶要求的解法。
解决关键有三个:
- 栈让我们能从最低位开始加。
- 头插法让结果保持从高位到低位。
- 进位逻辑保持标准大数加法的写法。