题目描述
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
例如:
解释:
因为是逆序保存的,所以2->4->3表示数字342, 同理得到465
342 + 465 = 807, 因此得到7->0->8
注意,两个链表并不一定长度相同,即可能20 + 300 = 320。
思路
首先理解为什么要用倒序表示一个数,因为链表只能从头结点开始遍历,分别表示个,十,百,千 … 因此只有倒序时,才符合我们的数学计算规则,从个位开始计算和,然后说十位,百位 …
该题的几个难点:
- 进位如何处理
- 不同长度的链表如何处理
难点1:进位如何处理
if (有进位) {sum = value1 + value2 + 进位;} else {sum = value1 + value2;}// 简化版本int carry = 0;while () {sum = value1 + value2 + carry;carry = sum / 10;sum = sum % 10;}
此为,如果 两个链表都遍历完了,最高位仍然有进位,需要再最高位补1
难点2: 不同长度的链表如何处理
对短链表的高位补0,例如240 + 32 = 240 + 032
小技巧
在处理链表问题时,通常会在头结点(Head)前面初始化一个dummy node, 主要原因是链表通常会涉及到指针的移动,例如在遍历之后,指针指向了最后一个结点,那么怎么返回该链表的头结点呢?技巧就是添加一个dummy node指向链表的头结点,那么最后只需要返回dummy.next即可。
代码
class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode dummy = new ListNode(0);// current首先指向dummy, 在遍历过程中仅移动current, 不再移动dummyListNode current = dummy;// 初始化carry为0int carry = 0;// 循环停止的条件为两个链表都为nullwhile (l1 != null || l2 != null) {// 当l1或者l2不为空时,value值即结点的值// 为空时,value值为0,就相当于是短的链表已经遍历到最后了,指向null了int value1 = l1 == null ? 0 : l1.val;int value2 = l2 == null ? 0 : l2.val;// 求和,该和可能大于10,产生新的carryint sum = value1 + value2 + carry;// 计算新的carry,例如,sum = 16, carry = 16 / 10 = 1;// Java中,两个整数相除,商为整数,直接丢弃了小数位carry = sum / 10;// 对sum取余得到新的sum, sum = 16, sum = 16 % 10 = 6;sum = sum % 10;// current的next指向新的结点current.next = new ListNode(sum);// current指向新结点current = current.next;// 移动l1和l2if (l1 != null) {l1 = l1.next;}if (l2 != null) {l2 = l2.next;}}// 如果都遍历完了,仍然有进位,需要最后补上进位结点// 事实上,两个个位数想加,carry最大也只会说1// 例如 999 + 999 即便每一位都是最大值,每一位都有进位,最高位也是9 + 9 + 1 = 19// 最高位的进位也不会超过1if (carry != 0) {current.next = new ListNode(carry);}return dummy.next;}}
