package class04;
/***
* 两个链表相加
* 给定两个链表的头节点head1和head2
* 认为从左到右是某个数字从低位到高位,返回相加之后的列表。
* 例子1:4->3->6 2->5->3
* 返回:6->8->9
* 解释:634 + 352 = 986
*
* 例子2:3->5->2 4->4->9
* 返回:7->9->1->1
* 解释:253 + 944 = 1197
*/
// 测试链接:https://leetcode.com/problems/add-two-numbers/
public class Code05_AddTwoNumbers {
//这个类不提交
public static class ListNode {
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public static ListNode addTwoNumbers(ListNode head1, ListNode head2) {
int size1 = listLength(head1);//获取链表1的长度
int size2 = listLength(head2);//获取链表2的长度
//如果链表1的长度大于等于链表2的长度,则返回head1,即较长链表的头节点。
ListNode l = size1 >= size2 ? head1 : head2;
//如果l就是head1,那么s就是head2(即head2就是较短链表的头节点);否则s就是head1(即head1就是较短链表的头节点。)
ListNode s = l == head1 ? head2 : head1;
ListNode curL = l;//当前轮的较长链表的头节点
ListNode curS = s;//当前轮的较短链表的头节点
//last:幽灵变量。始终指向当前回合的长链表的节点。
//作用只有一个,就是在第3阶段,有进位时,知道新增的节点,挂在哪。
ListNode last = curL;
int carry = 0;//进位
int curSum = 0;//当前回合,单链表的单个节点和短链表的单个节点的和。
//阶段1:短链表没走完(那么长链表肯定也没走完)。
while (curS != null) {
curSum = curL.val + curS.val + carry;//当前回合,长链表节点的值+短链表节点的值+进位
curL.val = curSum % 10;//将当前回合的和,对10取余,得到的值覆盖长链表的当前位置的值。
carry = curSum / 10;//求得是否有进位,即carry是0还是1。
//记录在当前回合,长链表的节点,跳步之前,的位置。
last = curL;
curL = curL.next;//长链表节点跳步。
curS = curS.next;//短链表节点跳步。
}
//阶段2:短链表做完了,但是长链表还没走完。
while (curL != null) {
curSum = curL.val + carry;
curL.val = curSum % 10;
carry = curSum / 10;
last = curL;
curL = curL.next;
}
//阶段3:长链表和短链表都走完了。
//判断是否有进位,如果没有进位,则结束,并返回。如果有进位,那么在长链表的尾结点的下一个节点,新增一个节点,并且值为1。
if (carry != 0) {
last.next = new ListNode(1);//新增节点,并且值为1,将它挂在长链表的尾结点的后一个位置。
}
return l;//较长链表的头节点
}
//获取链表的长度
public static int listLength(ListNode head) {
int size = 0;
while (head != null) {
size++;
head = head.next;
}
return size;
}
}