题目描述
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
输入: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]
解题思路
链表现在是倒序,但是我们把链表从头结点开始每一位匹配相加,正好跟我们做加法的顺序是一样的,每一次从l1,l2取出一个数,两两相加,把得到的和模10得到余数取出来作为新节点插入链表,把得到的和除以10得到进位记为flag参加下一次的运算
当两个链表的长度不一样时,从短的链表结束开始,把长的链表的剩下的元素考虑进位情况插入到新的链表中即可
我的提交
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int flag=0;//进位标识符
int l1_length=0;
int l2_length=0;
ListNode temp1=l1;
ListNode temp2=l2;
while(temp1!=null)//求链表1的长度
{
l1_length=l1_length+1;
temp1=temp1.next;
}
while(temp2!=null)//求链表2的长度
{
l2_length=l2_length+1;
temp2=temp2.next;
}
//先定义新链表的头结点
ListNode head= new ListNode ((l1.val+l2.val)%10);//取余数作为节点的值
ListNode cur=head;//保留head,用cur代替head,后续操作cur
flag=(l1.val+l2.val)/10;//求出进位
l1=l1.next;
l2=l2.next;
if(l1_length==l2_length)//两个链表长度相等
{
while(l1!=null)
{
cur.next= new ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
flag=(l1.val+l2.val+flag)/10;//取出进位
cur=cur.next; //这一句我是真怕形成环,但是还好过了
l1=l1.next;
l2=l2.next;
}
if(l1==null&&flag!=0)//考虑最后一位有进位的情况,比如[2,4,3],[5,6,8].输出[7,0,2,1]
{
cur.next=new ListNode(flag);
}
}
if(l1_length>l2_length)//l1链表长度大于l2链表
{
while(l2!=null)
{
cur.next=new ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
flag=(l1.val+l2.val+flag)/10;//取出进位
cur=cur.next;
l1=l1.next;
l2=l2.next;
}
while(l1!=null)//l2已经遍历完毕,现在考虑进位情况把l1剩下的部分插入新链表
{
cur.next=new ListNode((l1.val+flag)%10);
flag=(l1.val+flag)/10;
cur=cur.next;
l1=l1.next;
}
if(l1==null&&flag!=0)//考虑最后一位有进位的情况,比如l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]输出:[8,9,9,9,0,0,0,1]
{
cur.next=new ListNode(flag);
}
}
if(l1_length<l2_length)//l1链表长度小于l2链表
{
while(l1!=null)
{
cur.next=new ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
flag=(l1.val+l2.val+flag)/10;//取出进位
cur=cur.next;
l1=l1.next;
l2=l2.next;
}
while(l2!=null)
{
cur.next=new ListNode((l2.val+flag)%10);
flag=(l2.val+flag)/10;
cur=cur.next;
l2=l2.next;
}
if(l2==null&&flag!=0)//考虑最后一位有进位的情况,l2 = [9,9,9,9,9,9,9], l1 = [9,9,9,9]输出:[8,9,9,9,0,0,0,1]
{
cur.next=new ListNode(flag);
}
}
return head;
}
}
结果展示
简化代码
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int flag=0;//进位标识符
int l1_length=0;
int l2_length=0;
ListNode temp1=l1;
ListNode temp2=l2;
while(temp1!=null)//求链表1的长度
{
l1_length=l1_length+1;
temp1=temp1.next;
}
while(temp2!=null)//求链表2的长度
{
l2_length=l2_length+1;
temp2=temp2.next;
}
//先定义新链表的头结点
ListNode head= new ListNode ((l1.val+l2.val)%10);//取余数作为节点的值
ListNode cur=head;//保留head,用cur代替head,后续操作cur
flag=(l1.val+l2.val)/10;//求出进位
l1=l1.next;
l2=l2.next;
if(l1_length==l2_length)
{
while(l1!=null)
{
cur.next= new ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
flag=(l1.val+l2.val+flag)/10;//取出进位
cur=cur.next; //这一句我是真怕形成环,但是还好过了
l1=l1.next;
l2=l2.next;
}
if(l1==null&&flag!=0)//考虑最后一位有进位的情况,比如[2,4,3],[5,6,8].输出[7,0,2,1]
{
cur.next=new ListNode(flag);
}
}
if(l1_length>l2_length)
{
LengthNotEqual( l2, l1,cur,flag); //注意l1和l2的顺序,在LengthNotEqual函数中,是先判断比较短的链表是否遍历完毕,所以要把比较短的链表头放在第一个参数
}
if(l1_length<l2_length)
{
LengthNotEqual( l1, l2,cur,flag);
}
return head;
}
void LengthNotEqual(ListNode l1, ListNode l2,ListNode cur,int flag)
{
while(l1!=null)
{
cur.next=new ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
flag=(l1.val+l2.val+flag)/10;//取出进位
cur=cur.next;
l1=l1.next;
l2=l2.next;
}
while(l2!=null)
{
cur.next=new ListNode((l2.val+flag)%10);
flag=(l2.val+flag)/10;
cur=cur.next;
l2=l2.next;
}
if(l2==null&&flag!=0)//考虑最后一位有进位的情况
{
cur.next=new ListNode(flag);
}
}
}
再简化代码
其实,两个链表长度相等是可以和另外两种情况合在一起计算的
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int flag=0;//进位标识符
int l1_length=0;
int l2_length=0;
ListNode temp1=l1;
ListNode temp2=l2;
while(temp1!=null)//求链表1的长度
{
l1_length=l1_length+1;
temp1=temp1.next;
}
while(temp2!=null)//求链表2的长度
{
l2_length=l2_length+1;
temp2=temp2.next;
}
//先定义新链表的头结点
ListNode head= new ListNode ((l1.val+l2.val)%10);//取余数作为节点的值
ListNode cur=head;//保留head,用cur代替head,后续操作cur
flag=(l1.val+l2.val)/10;//求出进位
l1=l1.next;
l2=l2.next;
if(l1_length>=l2_length)
{
LengthNotEqual( l2, l1,cur,flag); //注意l1和l2的顺序,在LengthNotEqual函数中,是先判断比较短的链表是否遍历完毕,所以要把比较短的链表头放在第一个参数
}
if(l1_length<l2_length)
{
LengthNotEqual( l1, l2,cur,flag);
}
return head;
}
void LengthNotEqual(ListNode l1, ListNode l2,ListNode cur,int flag)
{
while(l1!=null)
{
cur.next=new ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
flag=(l1.val+l2.val+flag)/10;//取出进位
cur=cur.next;
l1=l1.next;
l2=l2.next;
}
while(l2!=null)
{
cur.next=new ListNode((l2.val+flag)%10);
flag=(l2.val+flag)/10;
cur=cur.next;
l2=l2.next;
}
if(l2==null&&flag!=0)//考虑最后一位有进位的情况
{
cur.next=new ListNode(flag);
}
}
}
总结
新创建链表时,定义链表头head之后,利用 cur=head,相当于复制了一份head,之后操作cur,不改变head,但是可以给链表追加节点
取余数 %10
取进位 /10
重复的代码可以封装为函数
构造函数直接创建新节点,不用为新节点指定名字,比如
cur.next=new ListNode(flag);
参考题解
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return this.addTwoNumbers2(l1, l2, 0);
}
public ListNode addTwoNumbers2(ListNode l1, ListNode l2, int a) {
if (l1 == null && l2 == null) {
return a == 0 ? null : new ListNode(a);
}
if (l1 != null) {
a += l1.val;
l1 = l1.next;
}
if (l2 != null) {
a += l2.val;
l2 = l2.next;
}
return new ListNode(a % 10, addTwoNumbers2(l1, l2, a / 10));
}
}
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return this.addTwoNumbers2(l1, l2, 0);
}
public ListNode addTwoNumbers2(ListNode l1, ListNode l2, int a) {
if (l1 == null && l2 == null) {
return a == 0 ? null : new ListNode(a);
}
if (l1 != null) {
a += l1.val;
l1 = l1.next;
}
if (l2 != null) {
a += l2.val;
l2 = l2.next;
}
ListNode node= new ListNode(a % 10);
node.next=addTwoNumbers2(l1, l2, a / 10);
return node;
}
}
迭代版本
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int carry=0;
ListNode head=new ListNode(0);
ListNode temp=head;
while(l1!=null||l2!=null||carry!=0){
int a=l1==null?0:l1.val;
int b=l2==null?0:l2.val;
carry=carry+a+b;
int val=carry%10;
carry/=10;
l1=l1==null?null:l1.next;
l2=l2==null?null:l2.next;
temp.next=new ListNode(val);
temp=temp.next;
}
return head.next;
}
}