445.两数相加
题目
给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例1:
输入:l1 = [7,2,4,3], l2 = [5,6,4]
输出:[7,8,0,7]
示例2:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[8,0,7]
示例3:
输入:l1 = [0], l2 = [0]
输出:[0]
提示:
链表的长度范围为 [1, 100]
0 <= node.val <= 9
输入数据保证链表代表的数字无前导 0
进阶:如果输入链表不能翻转该如何解决?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解1
第一个问题就是如何对齐,链表长度是不一样的,谁与谁相加?
长度不一样,我们可以通过在短链表前面添加0节点,是两个链表长度一样,那么头节点对头节点,尾节点对尾节点就对齐了。
ListNode tail1 =l1;
ListNode tail2 =l2;
//都走到最后一个节点就停止添加
while(tail1.next==null && tail2.next==null){
if(tail1.next == null){
//说明到尾了但是还在循环里说明tail2还没有到尾
ListNode tmp = new ListNode(0);
tmp.next = l1;
l1 = tmp;
}
if(tail2.next == null){
ListNode tmp = new ListNode(0);
tmp.next = l2;
l2 = tmp;
}
tail1 = tail1.next ==null ? tail1 : tail1.next;
tail2 = tail1.next ==null ? tail2 : tail2.next;
}
处理完对齐的问题后,如何处理相加?相加是从低位开始相加,如果有进位需要向前一位传递。
而链表的遍历顺序一般是从左到右,现在我们需要从右到左,那么可以翻转链表,加完之后再翻转回来。
//翻转链表
ListNode reverseList(ListNode head){
ListNode pre=null;
ListNode tmp;
while(head!=null){
tmp = head.next; //防止断链,记录下要反转的节点的后一个节点
head.next = pre; //开始反转指向前一个
pre = head;
head = tmp;
}
return pre; //返回新的头节点
}
开始计算,这里的指针有点多,整理一下
tail1 指向 l1 的最后一个节点,也就是翻转后的头节点,l1指向翻转后的最后一个节点
tail2 指向 l2 的最后一个节点,也就是翻转后的头节点,l2指向翻转后的最后一个节点
ListNode pre = reverseList(l1);
reverseList(l2);
int flag = 0 ;//表示十位
while(tail1!=null){//长度是一样的
tail1.val = (tail1.val + tail2.val+flag)%10; //取个位数
flag = (tail1.val + tail2.val+flag)/10; //取十位数
tail1 = tail.next();
}
if(flag!=0) 添加一个节点
reverseList(pre);
return l1;
代码
现在整理一下所有思路,发现如果先翻转链表,那可以不用补节点了,翻转之后,都从头开始个位数自然会对齐。如果遇见null就算0。
新链表采用头插法就不用再翻转一次了。
l1 = reverseList(l1); //指向新的头节点
l2 = reverseList(l2); //翻转链表
int flag = 0 ;//表示十位
int val1=0,val2=0;
ListNode dummy = new ListNode(); //新链表的头节点
ListNode tmp;
ListNode newHead;
//做加法,不同时为空,同时为空说明已经加完了
while(!(l1==null && l2==null)){
val1 = l1 == null? 0 : l1.val;
val2 = l2 == null? 0 : l2.val;
tmp = dummy.next;
newHead = new ListNode((val1 + val2+flag)%10); //取个位数
dummy.next = newHead;
newHead.next = tmp;
flag = (val1 + val2+flag)/10; //取10位数
//遍历下一个节点
l1 = l1 == null? null:l1.next;
l2 = l2 == null? null: l2.next;
}
//flag如果有值,说明进位只有还需要添加一个节点
if(flag!=0){
newHead = new ListNode(flag);
tmp = dummy.next;
dummy.next = newHead;
newHead.next = tmp;
}
return dummy.next;
//翻转链表
ListNode reverseList(ListNode head){
ListNode pre=null;
ListNode tmp;
while(head!=null){
tmp = head.next; //防止断链,记录下要反转的节点的后一个节点
head.next = pre; //开始反转指向前一个
pre = head;
head = tmp;
}
return pre; //返回新的头节点
}
题解2
逆序处理:还可以通过栈
总结
逆序遍历链表
- 翻转链表
- 栈