给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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
- 题目数据保证列表表示的数字不含前导零
【分析】
要求将链表进行逆序存储,然后将链表的每位数字进行相加,并且每个位置只能存储一个数字。
如果是正序的话满足原则:从右向左,对位相加,逢十进一的原则,那么对于本题逆序而言也是遵循的,只不过是从左向右,对位相加,逢十进一。最后的结果依然按照逆序输出。(也就是说,如果按照逆序进行相加,我们需要将最后的结果进行逆序。由于输入的两个链表都是逆序存储数字的位数的,因此两个链表中同一位置的数字可以直接相加,这样得到的结果最后就是逆序的。比如输入243和564,我们按照逆序加是807,最后要逆序输出708。如果我们直接对同一位置数字进行相加,2+5=7,4+6=10,向前进1,3+4+1=8,最后输出依然是708。)
先定义一个链表3,用来输出最后的结果。刚开始,l3指向空,然后定义一个移动指针p,刚开始指向l3。定义一个进位,初始值赋为0。
当两个链表均不为空的时候,首先定义一个节点num,用来表示l1+l2的值。在加的过程中,我们需要考虑前面两个数加的有没有进位,如果有需要进一起加入。因此,我们num可以表示为num->val=(l1->val+l2->val+jinwei)%10,对10去余是为了将进位去除,只留下一位数字(比如相加为11,那么num应该等于1,然后向前面进1位;比如相加为23,那么num应该等于3,然后向前面进2位),而对于每次加的进位,同意需要计算,可通过jinwei=(l1->val+l2->val+jinwei)/10,对10求商,商为进位。(比如相加为11,那么jinwei应该为1位;比如相加为23,那么jinwei应该为1位2)。求出num后,需要将p的后继指向num,然后将p指向p的后继。最后将l1和l2向后遍历重复上述工作。
当其他有一个链表为空的时候,不能直接加入到l3中,而是要考虑进位(可能两个链表中最后产生的和有进位),流程和两个链表均为空时一致,只不过去掉已经为空的链表即可。
最后需要考虑有没有剩下进位,如果进位不为零,需要将进位加入到l3中。并且返回l3的后续节点(也就是要求的结果)
具体案例分析1:
1 = [2,4,3], l2 = [5,6,4]
首先l3=p->NULL,num=7(2+5=7,取余后为7),jinwei=0(2+5=7,取商后为0);然后l3->7(此时p指向7)
l3->7(此时p指向7),num=0(6+4=10,取余后为0),jinwei=1(6+4=10,取商后为1);然后l3->7->0(此时p指向0)
l3->7->0(此时p指向0),num=8(3+4+1=8,取余后为8),jinwei=1(3+4+1=8,去商后为0);然后l3->7->0->8(此时p指向8)
具体案例分析2:
l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
首先l3=p->NULL,num=8(9+9=18,取余后为8),jinwei=0(9+9=18,取商后为1);然后l3->8(此时p指向8)
l3->8(此时p指向8),num=9(9+9+1=19,取余后为9),jinwei=0(9+9+1=19,取商后为1);然后l3->8->9(此时p指向9)
l3->8->9(此时p指向9),num=9(9+9+1=19,取余后为9),jinwei=0(9+9+1=19,取商后为1);然后l3->8->9->9(此时p指向最后一个9)
l3->8->9->9(此时p指向最后一个9),num=9(9+9+1=19,取余后为9),jinwei=0(9+9+1=19,取商后为1);然后l3->8->9->9->9(此时p指向最后一个9)
l3->8->9->9->9(此时p指向最后一个9),此时链表2为空,只用看链表,num=0(9+1=10,取余后为0),jinwei=1(9+1=10,取商后为1);然后l3->8->9->9->9->0(此时p指向0)
l3->8->9->9->9->0(此时p指向最后一个9),此时链表2为空,只用看链表,num=0(9+1=10,取余后为0),jinwei=1(9+1=10,取商后为1);然后l3->8->9->9->9->0->0(此时p指向最后一个0)
l3->8->9->9->9->0->0(此时p指向最后一个0),此时链表2为空,只用看链表,num=0(9+1=10,取余后为0),jinwei=1(9+1=10,取商后为1);然后l3->8->9->9->9->0->0->0(此时p指向最后一个0)
3->8->9->9->9->0->0->0(此时p指向最后一个0)此时链表1和2均为空,但是进位剩下一个一,因此需要将进位加入。l3->8->9->9->9->0->0->0->1(此时p指向一个1)
最后返回l3->next=[8,9,9,9,0,0,0,1]
C语言具体代码如下:
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
struct ListNode* l3=(struct ListNode*)malloc(sizeof(struct ListNode));
l3->next=NULL;
struct ListNode* p=l3;
int jinwei=0;
while(l1 != NULL && l2 != NULL){//从前往后进行相加
struct ListNode *num=(struct ListNode*)malloc(sizeof(struct ListNode));
num->next=NULL;
num->val=(l1->val+l2->val+jinwei)%10;
jinwei=(l1->val+l2->val+jinwei)/10;
p->next=num;
p=p->next;
l1=l1->next;
l2=l2->next;
}
while(l1 != NULL){ //链表2为空的时候,只剩下链表1
struct ListNode *num=(struct ListNode*)malloc(sizeof(struct ListNode));
num->next=NULL;
num->val=(l1->val+jinwei) % 10;
jinwei=(l1->val+jinwei) / 10;
p->next=num;
p=p->next;
l1=l1->next;
}
while(l2 != NULL){ //链表1为空的时候,只剩下链表2
struct ListNode *num=(struct ListNode*)malloc(sizeof(struct ListNode));
num->next=NULL;
num=(l2->val+jinwei) % 10;
jinwei=(l2->val+jinwei) / 10;
p->next=num;
p=p->next;
l2=l2->next;
}
if(jinwei != 0){//最后还剩下进位时
struct ListNode *num=(struct ListNode*)malloc(sizeof(struct ListNode));
num->next=NULL;
num->val=jinwei;
p->next=num;
}
return l3->next;
}
时间复杂度O(max(m,n));空间复杂度 O(max(m,n))