两个链表相加
// 给你两个 非空 的链表,表示两个非负的整数
// 它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字
// 请你将两个数相加,并以相同形式返回一个表示和的链表。
// 你可以假设除了数字 0 之外,这两个数都不会以 0 开头
// 测试链接:https://leetcode.cn/problems/add-two-numbers/
public class AddTwoNumbers {
// 不要提交这个类
public static class ListNode {
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
class Solution {
// 也可以复用老链表
// 不过这个实现没有这么做,都是生成的新节点(为了教学好懂)
public static ListNode addTwoNumbers(ListNode h1, ListNode h2) {
ListNode ans = null, cur = null;
int carry = 0;
for (int sum, val; // 声明变量
h1 != null || h2 != null; // 终止条件
h1 = h1 == null ? null : h1.next, // 每一步h1的跳转
h2 = h2 == null ? null : h2.next // 每一步h2的跳转
) {
sum = (h1 == null ? 0 : h1.val)
+ (h2 == null ? 0 : h2.val)
+ carry;
val = sum % 10;
carry = sum / 10;
if (ans == null) {
ans = new ListNode(val);
cur = ans;
} else {
cur.next = new ListNode(val);
cur = cur.next;
}
}
if (carry == 1) {
cur.next = new ListNode(1);
}
return ans;
}
}
}
从结构、数据流、循环逻辑、进位处理、边界判断等角度,一层层给你解释清楚
🧱 一、整体功能概述
该代码的功能是:
给定两个 非空的正序链表,每个节点代表一位数字,两个链表从 低位到高位 存储,例如:
输入: (2 -> 4 -> 3) + (5 -> 6 -> 4) 表示: 342 + 465 = 807 输出: 7 -> 0 -> 8
🧱 二、类的结构说明
🔹 外部类 AddTwoNumbers
包含两部分:
1. ✅ 内部类 ListNode
表示链表节点结构,有两个构造器:
public int val; // 节点的值
public ListNode next; // 指向下一个节点的指针
2. ✅ 内部类 Solution
包含核心算法方法 addTwoNumbers,这是你最终要调用的方法。
🧠 三、函数 addTwoNumbers 的完整解释
public static ListNode addTwoNumbers(ListNode h1, ListNode h2)
该函数接受两个链表头节点 h1 和 h2,返回结果链表的头节点。
✅ 变量初始化:
ListNode ans = null, cur = null; // 最终答案链表 & 当前尾指针
int carry = 0; // 进位,初始为 0
-
ans:指向结果链表的头结点 -
cur:在构造链表时的尾指针 -
carry:表示两个数字相加后的进位值(只可能是 0 或 1)
✅ 核心 for 循环:
for (int sum, val; h1 != null || h2 != null;
h1 = h1 == null ? null : h1.next,
h2 = h2 == null ? null : h2.next)
等价于 while 结构,只是写得紧凑而优雅。
🔁 每次循环做的事:
sum = (h1 == null ? 0 : h1.val) + (h2 == null ? 0 : h2.val) + carry;
- 把当前两个节点的值 + 上一轮进位
val = sum % 10;
carry = sum / 10;
-
val是当前节点的值(个位) -
carry是进位(十位)
✅ 构造新节点:
if (ans == null) {
ans = new ListNode(val); // 第一个节点,初始化头
cur = ans;
} else {
cur.next = new ListNode(val); // 后续节点
cur = cur.next;
}
第一轮用 ans 建立头节点,后续使用 cur 往后追加新节点。
✅ 最后加上尾部进位:
if (carry == 1) {
cur.next = new ListNode(1);
}
如果两个链表都加完还有一个进位(比如 999 + 1 = 1000),需要加个多余节点补上。
📌 四、举个例子手动模拟一遍
输入:
l1: 2 -> 4 -> 3 (表示 342)
l2: 5 -> 6 -> 4 (表示 465)
运算过程:
Step 1: 2 + 5 + 0 = 7 → 结果链表:7
Step 2: 4 + 6 + 0 = 10 → 结果链表:7 -> 0(进位 1)
Step 3: 3 + 4 + 1 = 8 → 结果链表:7 -> 0 -> 8
输出:
7 -> 0 -> 8
🧠 五、代码优点总结
| 点 | 描述 |
|---|---|
| ✅ 简洁优雅 | 使用 for 循环同时处理 h1 和 h2 的遍历,简化代码 |
| ✅ 可扩展 | 可以处理两个不同长度的链表 |
| ✅ 可维护 | 清晰的变量名和结构 |
| ✅ 教学清晰 | 所有新节点都显式创建,便于初学者理解,不复用原链表结构 |
✅ 最终总结一句话:
这段代码实现的是 两个逆序存储的链表加法,模拟的是 小学的竖式加法 + 链表构建 的过程。
它通过逐节点相加 + 模 10 取余 + 进位处理,构造出一个新的结果链表。

浙公网安备 33010602011771号