445.两数相加Ⅱ

目录

445.两数相加

题目

给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

示例1:
445.两数相加Ⅱ

输入: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

逆序处理:还可以通过栈

总结

逆序遍历链表

  • 翻转链表
上一篇:网安——445漏洞破解


下一篇:CMU CS15-445 Lecture01 关系模型 课程笔记