前言说明
算法学习,日常刷题记录。
题目连接
题目内容
给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字0之外,这两个数都不会以0开头。
示例1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807
示例2:
输入:l1 = [0], l2 = [0]
输出:[0]
示例3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
提示:
每个链表中的节点数在范围[1, 100]内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零
分析过程
如果是把两个链表的值转换出来,两个值相加得到新值,新值再转为链表,这是不可行的。
因为范围太大了,每个链表中的节点数在范围[1, 100]内,最大已经达到了100位的数,在链表转为值时可能会溢出,导致转的值不正确。
这道题需要使用模拟的方法,按照我们平时两数相加的竖式计算的思路走,同时从头到尾遍历两个链表,构造出两数之和的链表。
第一步
定义计算两数之和的链表的中间节点node,在竖式计算过程需要用来保存中间节点。
定义两数之和的链表head,head初始指向node,在最后直接返回head就是答案。
定义是否进位isCarry,初始为false,在竖式计算过程需要用来处理进位。
第二步
while循环,模拟竖式计算,同时从头到尾遍历两个链表l1、l2,构造出两数之和的链表,当两个链表l1、l2都为空时结束循环。
第三步
每次while循环时:
1、定义竖式计算时两数相加的结果val,分别处理两个链表l1、l2,处理链表时,先赋值累加给val,再把自身指向下一个节点的指针next,
2、通过是否进位的标识isCarry判断当前是否有进位,如果有进位,val加1。
3、通过判断val是否大于9,更新是否进位的标识isCarry。
4、若val大于9,val减10取个位数。
5、把val赋给中间节点node的值。
6、若两个链表l1、l2还不是都为空,那么后面还会再有节点,否则后面没有节点了,构造下一个节点时,通过把中间节点node的下一个节点指针next指向一个新构造的节点来完成,再把中间接节点node自身指向它的下一个节点node.next,在下一次循环时就能把下一个值赋给下一个节点。
第四步
while循环结束后,若还有进位,那么前面构造出来的链表要往后添加一个节点,即在链表的最后一个节点添加它的下一个节点,即中间节点node的下一个节点指针next指向一个新构造的节点,新构造的节点的值为1。
第五步
返回两数之和的链表head,结束程序。
解答代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
// 模拟,按照两数相加的竖式计算的思路走,同时从头到尾遍历两个链表,构造出两数之和的链表
// 定义计算两数之和的链表的中间节点
ListNode node = new ListNode();
// 定义两数之和的链表
ListNode head = node;
// 定义是否进位
boolean isCarry = false;
// 循环,模拟竖式计算,同时从头到尾遍历两个链表,构造出两数之和的链表,当两个链表都为空时结束循环
while (l1 != null || l2 != null) {
// 定义竖式计算时两数相加的结果
int val = 0;
// 处理第一个链表
if (l1 != null) {
val += l1.val;
l1 = l1.next;
}
// 处理第二个链表
if (l2 != null) {
val += l2.val;
l2 = l2.next;
}
// 如果前面有进位,两数相加的结果加1
val = isCarry ? val + 1 : val;
// 判断当前位是否有进位,若大于9,则需要进位
isCarry = val > 9;
if (val > 9) {
// 若大于9,则减10取个位数
val = val - 10;
}
// 把两数相加的结果赋给新链表的节点
node.val = val;
if (l1 != null || l2 != null) {
// 若两个链表都为空,那么后面不会再有节点,所以如果新链表后面不进位,那么后面也不会再有节点
node.next = new ListNode();
node = node.next;
}
}
if (isCarry) {
// 如果新链表后面进位,那么要补充一位
node.next = new ListNode(1);
}
// 返回两数之和的链表
return head;
}
}
提交结果
执行用时2ms,时间击败96.94%的用户,内存消耗38.7MB,空间击败52.44%的用户。
原文链接
原文链接:两数相加