题目描述
给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例
输入:l1 = [2, 4, 3],l2 = [5, 6, 4]
输出:[7, 0, 8]
解释:342 + 465 = 807
解题思路
解题策略是采用类似于手算加法的进位机制,遍历两个链表,处理每一位的加法和进位,最后返回新的链表表示结果。这种方法避免了将链表转换为整数导致的溢出问题。
解题步骤
1.初始化:创建一个哑节点(dummy node)作为结果链表的头部,它可以帮助简化边界条件的处理(例如,当结果链表只有一个节点时)。同时,初始化一个进位变量carry为0。
2.遍历链表:同时遍历两个链表l1和l2,直到它们都到达末尾。在每一步中,取出l1和l2当前节点的值(如果某个链表已经遍历完,则将其值视为0),将它们与进位变量carry相加,得到当前位的和。然后,更新进位变量carry为当前和除以10的商,将当前和的个位数创建为一个新节点,并连接到结果链表的末尾。
3.处理进位:在遍历完两个链表后,如果进位变量carry仍然大于0,则需要在结果链表的末尾再添加一个值为carry的新节点。
4.返回结果:返回哑节点的下一个节点作为结果链表的头部(因为哑节点本身不存储有效值)。
解题代码(JavaScript)
var addTwoNumbers = function(l1, l2) {
// 创建一个哑节点作为结果链表的头部
let dummy = new ListNode(0);
let current = dummy; // 当前节点指针
let carry = 0; // 进位
// 遍历两个链表
while (l1 !== null || l2 !== null) {
let x = (l1 !== null) ? l1.val : 0; // 如果l1不为空,则取l1的值,否则取0
let y = (l2 !== null) ? l2.val : 0; // 同理,对l2做相同的处理
let sum = carry + x + y; // 计算当前位的和(包括进位)
carry = Math.floor(sum / 10); // 更新进位
// 创建一个新节点存储当前位的和(取个位数)
current.next = new ListNode(sum % 10);
current = current.next; // 移动当前节点指针
// 如果l1和l2还有剩余节点,则继续遍历
if (l1 !== null) l1 = l1.next;
if (l2 !== null) l2 = l2.next;
}
// 如果遍历结束后还有进位,则在结果链表末尾再添加一个节点
if (carry > 0) {
current.next = new ListNode(carry);
}
// 返回哑节点的下一个节点作为结果链表的头部
return dummy.next;
};
// 辅助函数:用于创建链表节点
function ListNode(val, next) {
this.val = (val === undefined ? 0 : val);
this.next = (next === undefined ? null : next);
}
// 示例用法
// 创建链表 2 -> 4 -> 3
let l1 = new ListNode(2);
l1.next = new ListNode(4);
l1.next.next = new ListNode(3);
// 创建链表 5 -> 6 -> 4
let l2 = new ListNode(5);
l2.next = new ListNode(6);
l2.next.next = new ListNode(4);
// 调用函数并输出结果链表
let result = addTwoNumbers(l1, l2);
// 打印结果链表
let currentResult = result;
while (currentResult !== null) {
console.log(currentResult.val);
currentResult = currentResult.next;
}