2. 两数相加
题目
原题链接:https://leetcode-cn.com/problems/add-two-numbers/
给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
如果,将这两个数相加起来,则会返回一个新的链表来表示它们的和。除了数字0之外,这两个数都不会以0开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
解题思路
- 同时遍历两个链表,逐位计算它们的和,并与当前位置的进位值相加。
- 如果当前两个链表处相应位置的数字为\(n1,n2\),进位值为\(\textit{carry}\),则它们的和为 \(n1+n2+\textit{carry}\);其中,答案链表处相应位置的数字为\((n1+n2+\textit{carry}) \% 10\),而新的进位值为\(\lfloor\frac{n1+n2+\textit{carry}}{10}\rfloor\)。
- 将两个链表看成是相同长度的进行遍历,如果一个链表较短则在前面补\(0\),如\(789 + 32 = 789 + 320 = 00101\)
- 如果链表遍历结束后,有\(\textit{carry} > 0\),还需要在答案链表的后面附加一个节点,节点的值为\(\textit{carry}\)。
- 小技巧:对于链表问题,返回结果为头结点时,通常需要先初始化一个预先指针preNode,该指针的下一个节点指向真正的头结点head。使用预先指针的目的在于,链表初始化时无可用节点值,而且链表构造过程需要指针移动,进而会导致头指针丢失,无法返回结果。
代码实现
/**
* 2.两数相加
* @author chenzufeng
*/
public class AddTwoNumbers {
public static ListNode addTwoNumbers(ListNode listNode1, ListNode listNode2) {
// 进位标志
int carry = 0;
// 结果链表头节点的前一个节点
ListNode preNode = new ListNode();
ListNode currentNode = preNode;
while (listNode1 != null || listNode2 != null) {
int sum = carry;
sum += (listNode1 != null ? listNode1.value : 0);
sum += (listNode2 != null ? listNode2.value : 0);
carry = sum / 10;
currentNode.nextNode = new ListNode(sum % 10);
currentNode = currentNode.nextNode;
// 查看两个链表的下一位
if (listNode1 != null) {
listNode1 = listNode1.nextNode;
}
if (listNode2 != null) {
listNode2 = listNode2.nextNode;
}
}
// 两个链表都到了尾端,此时还有进位
if (carry == 1) {
currentNode.nextNode = new ListNode(carry);
}
return preNode.nextNode;
}
}