文章目录
- 一、题目简介
- 二、题目分析
- 三、解题思路讲解
-
- [1. 基本思路:模拟加法过程](#1. 基本思路:模拟加法过程)
- [2. 示例演算](#2. 示例演算)
- 四、Java代码实现
- 五、时间复杂度与空间复杂度分析
一、题目简介
题目链接:LeetCode 两数相加
题目描述:
给定两个非空的链表,它们表示两个非负整数。数字按照逆序存储在链表中,每个节点只存储单个数字。请将这两个数相加,并以相同形式(逆序链表)返回一个新的链表。
示例:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807
二、题目分析
这道题的关键在于:
- 链表形式的数值相加
- 逆序存储
- 进位处理
思维导图
两数相加问题
题目要求
逆序链表
逐位相加
处理进位
解法方向
模拟加法
同时遍历两个链表
维护进位变量carry
构建新链表
优化思路
使用哑节点 dummyHead
简化链表操作
三、解题思路讲解
1. 基本思路:模拟加法过程
核心思想:
我们按照小学算术加法的方式,逐位相加:
- 同时遍历两个链表;
- 如果某一链表已遍历完,则视其当前值为 0;
- 计算当前节点值:
sum = l1.val + l2.val + carry - 取个位作为新节点值:
newNode.val = sum % 10 - 更新进位:
carry = sum / 10 - 最后如果 carry ≠ 0,需要额外补一个节点表示进位。
流程图示意
是
否
开始
初始化 dummyHead, carry=0
同时遍历链表 l1 和 l2
sum = val1 + val2 + carry
新节点值 = sum % 10
carry = sum / 10
添加新节点到结果链表
是否还有节点或进位?
返回 dummyHead.next
结束
2. 示例演算
以题中示例链表为例:
l1: 2 → 4 → 3 (代表342)
l2: 5 → 6 → 4 (代表465)
逐步相加过程:
| 步骤 | l1.val | l2.val | carry | sum | 新结点值 | 新的carry |
|---|---|---|---|---|---|---|
| 第一步 | 2 | 5 | 0 | 7 | 7 | 0 |
| 第二步 | 4 | 6 | 0 | 10 | 0 | 1 |
| 第三步 | 3 | 4 | 1 | 8 | 8 | 0 |
最终链表结果为:7 → 0 → 8
表示整数 807。
四、Java代码实现
以下是完整的 Java 实现,结构清晰、易读性高:
java
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
}
}
public class AddTwoNumbers {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(0); // 哑节点
ListNode current = dummyHead;
int carry = 0;
while (l1 != null || l2 != null || carry != 0) {
int val1 = (l1 != null) ? l1.val : 0;
int val2 = (l2 != null) ? l2.val : 0;
int sum = val1 + val2 + carry;
carry = sum / 10;
current.next = new ListNode(sum % 10);
current = current.next;
if (l1 != null) l1 = l1.next;
if (l2 != null) l2 = l2.next;
}
return dummyHead.next;
}
}
五、时间复杂度与空间复杂度分析
| 项目 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(max(m, n)) | 需要遍历两个链表的长度 |
| 空间复杂度 | O(max(m, n)) | 新链表节点的数量与较长链表相同 |
不存在额外的集合存储,仅需常数空间保存 carry 和若干指针。