题目描述
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入: l1 = [2,4,3], l2 = [5,6,4]
输出: [7,0,8]
解释: 342 + 465 = 807.
示例 2:
输入: l1 = [0], l2 = [0]
输出: [0]
示例 3:
输入: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出: [8,9,9,9,0,0,0,1]
提示:
- 每个链表中的节点数在范围
[1, 100]内 0 <= Node.val <= 9- 题目数据保证列表表示的数字不含前导零
链表结构如下:
public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
解题思路
题目将10进制整数用链表进行表示,每一位存储在一个节点中,往表头的方向为低位,往表尾的方向为高位。
由于10进制整数的每一位只能是0~9之间的整数,因此我们可以判断每两个节点之和最多不超过18,即如果两个数的同位相加产生了进位,只有可能是进1;同时产生进位的情况下,剩下的低位数字最大为8,此时如果更低一位的数字也产生了进位,那么最大结果就是8+1=9,即不存在同一位数在一次运算中出现两次进位的情况。
基于以上,我们可以声明整形变量v1, v2,分别存储链表l1, l2遍历过程中相同数位节点的值。将v1与v2相加之后,十位数存储在一个整型变量flag中,代表产生进位的情况,根据以上分析可知flag的值只会是0或1;个位数则与前一次得到的flag相加作为新的节点存储在结果链表res中。
最后,不排除最高位产生进位的情况,此时便需要在res末尾加上值位1的节点。
最终代码
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
// flag存储进位,v1、v2存储节点中的数
int flag = 0, v1, v2;
ListNode p1 = l1, p2 = l2, res = new ListNode(), pRes = res;
while (p1 != null || p2 != null) {
// p1或p2为null代表该数位为0
v1 = p1 == null ? 0 : p1.val;
v2 = p2 == null ? 0 : p2.val;
// 同位数与上一位数的进位相加,个位数作为新节点
pRes.next = new ListNode((v1 + v2 + flag) % 10);
// 十位数作为进位
flag = (v1 + v2 + flag) / 10;
pRes = pRes.next;
if (p1 != null) p1 = p1.next;
if (p2 != null) p2 = p2.next;
}
// 判断最高位的进位情况
if (flag == 1) {
pRes.next = new ListNode(1);
}
return res.next;
}