两个链表相加


// 给你两个 非空 的链表,表示两个非负的整数
// 它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字
// 请你将两个数相加,并以相同形式返回一个表示和的链表。
// 你可以假设除了数字 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)

该函数接受两个链表头节点 h1h2,返回结果链表的头节点。


✅ 变量初始化:

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 取余 + 进位处理,构造出一个新的结果链表。


posted @ 2025-07-17 14:11  ji415  阅读(14)  评论(0)    收藏  举报