445.两数相加Ⅱ
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){ //这个可以添加在while条件里面!!
	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-栈
逆序处理:还可以通过栈
从头节点开始入栈,出栈的顺序刚好是逆序的顺序
//入栈 两个链表全部入栈则停止入栈
while(l1!=null){
		stack1.push(l1);
		l1 = l1.next;
}
while(l2!=null){
	stack2.push(l2);
	l2 = l2.next;
}
//出栈相加,构建新的链表,采用头插法,保证顺序一致
ListNode dummy = new ListNode(); //新链表的头节点
ListNode newHead,tmp;
int flag = 0 ;//表示十位
int val1=0,val2=0;
//两个栈为空,说明数据都取出来了
while(!(stack1.empty() &&stack2.empty())){
	val1 = !stack1.empty()? stack1.pop().val:0;
	val2 = !stack2.empty() ? stack2.pop().val:0;
	//构建新链表
	tmp = dummy.next;
	newHead = new ListNode((val1 + val2+flag)%10); //取个位数
	dummy.next = newHead;
	newHead.next = tmp;
	flag = (val1 + val2+flag)/10;  //取10位数
}
//flag如果有值,说明进位只有还需要添加一个节点
if(flag!=0){ //与while 里内容重合可以进行简化
	newHead = new ListNode(flag);
	tmp = dummy.next;
	dummy.next = newHead;
	newHead.next = tmp;
}
//简化if部分
//两个栈为空,说明数据都取出来了,并且flag==0说明新节点构建完成
while(!(stack1.empty() &&stack2.empty()&&flag==0)){
	val1 = stack1.peek() ? stack1.pop():0;
	val2 = stack2.peek() ? stack2.pop():0;
	//构建新链表
	tmp = dummy.next;
	newHead = new ListNode((val1 + val2+flag)%10); //取个位数
	dummy.next = newHead;
	newHead.next = tmp;
	flag = (val1 + val2+flag)/10;  //取10位数
}
代码
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        Stack <ListNode> stack1 = new Stack<>(); 
        Stack <ListNode> stack2 = new Stack<>(); 
while(!(l1==null && l2==null)){
	if(l1!=null){
		stack1.push(l1);
		l1 = l1.next;
	}
	if(l2!=null){
		stack2.push(l2);
		l2 = l2.next;
	}
}
ListNode dummy = new ListNode(); 
ListNode newHead,tmp;
int flag = 0 ;
int val1=0,val2=0;
while(!(stack1.empty() &&stack2.empty()&&flag==0)){
	val1 = !stack1.empty()? stack1.pop().val:0;
	val2 = !stack2.empty() ? stack2.pop().val:0;
	tmp = dummy.next;
	newHead = new ListNode((val1 + val2+flag)%10); //取个位数
	dummy.next = newHead;
	newHead.next = tmp;
	flag = (val1 + val2+flag)/10;  //取10位数
}
return dummy.next;
    }
}
总结
逆序遍历链表
- 翻转链表
- 栈
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号