题目:
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法1,常规解法
carry代表进位,由于进位只考虑对下一位的影响,所以每一次循环中,分别可能有要进位与不用进位的情况,都分别赋值carry=1和carry=0,否则在第一次进位后,carry一直为1。
由于最终要返回指向该链表的指针,所以定义了一个temp=p来存放起始位置,否则在不断创建新节点的过程中,单向链表将无法重新访问头节点。
注意在循环结束后,得到的和的数字的位数将于两个链表的其中的最长位数相同,故对于999+9999这样末尾还要进一位的就会有缺失,故在退出循环时加一层判断如果carry==1,说明还有一个进位没进,则p重新添加一个节点,并使val=1。
也可:不用carry作为flag来记录是否需要进位,而是再判断后,直接对p添加一个节点,并使那个节点的val=1,再把运算从p->val=l1->val+l2->val改成p->val+=l1->val+l2->val
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* add();
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
struct ListNode*p=add();
struct ListNode*temp=p;
int carry=0;
while(1)
{
if((l1->val+l2->val+carry)>=10)
{
p->val=l1->val+l2->val-10+carry;//此时的carry是上一轮循环得到的carry
carry=1;
}
else
{
p->val=l1->val+l2->val+carry;//此时的carry是上一轮循环得到的carry
carry=0;
}
if(l1->next!=NULL||l2->next!=NULL)//都到末尾时不满足if
{
if(l1->next==NULL)l1->next=add();
if(l2->next==NULL)l2->next=add();
l1=l1->next;
l2=l2->next;
p->next=add();
p=p->next;
}
else break;
}
if(carry==1)
{
p->next=add();
p=p->next;
p->val=1;
}
return temp;
}
struct ListNode* add()
{
struct ListNode*list=(struct ListNode*)malloc(sizeof(struct ListNode));
list->val=0;
list->next=NULL;
return list;
}
进阶解法:递归
转载:
实现两个链表的每个节点互相加和,然后输出。这个题的关键点在于进位。
当某个节点的和大于10之后,需要向前进1位,在进位之后可能下一个节点之和加上进的1可能又会大于10,故我们可以使用递归的算法来完成这道题。
这题还有一个容易出现的问题,那就是两个链表不等长,当一个长一个短的时候,我们在判断链表是否到达终点将出现困难,我的策略是:如果其中一个链表的 next==Null那么我们使用malloc函数给他补上一个,让他的val==0这样即对我们的加和没有影响,又可以使两根链表等长。
struct ListNode* addNode();
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
l1->val = l1->val+l2->val;
if(l1->val>=10)
{ //进位
l1->val -= 10;
if(l1->next==NULL)
{ //如果下一个为空了,则补一个节点再进位
l1->next = addNode();
l1->next->val += 1;
}
else
{
l1->next->val += 1;
}
}
//两个链表都没有下一个节点,且不需要进位则直接输出
if(l1->next==NULL&&l2->next==NULL&&l1->val<10)
{
return l1;
}
//判断l1下一个是否位空
if(l1->next!=NULL)
{
//l1、l2下一个都不为空
if(l2->next!=NULL)
{
//则直接递归
l1->next = addTwoNumbers(l1->next,l2->next);
}
else
{
//l1不空,l2空,则补一个节点给他再递归
l2->next = addNode();
addTwoNumbers(l1->next,l2->next);
}
}
else
{
//l1空,则补节点再递归
l1->next = addNode();
l1->next = addTwoNumbers(l1->next,l2->next);
}
//返回l1的指针
return l1;
}
/*
用于在一个链表到终点后,另一个链表还未到。添加一个节点上去
*/
struct ListNode* addNode(){
struct ListNode* listt=(struct ListNode*)malloc(sizeof(struct ListNode));
listt->val=0;
listt->next=NULL;
return listt;
}