两个数字相加
题干
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
解题代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){ /* 思路: 1.同时遍历两个链表,直到两个链表都为空为止 2.考虑进位的问题 何时进位 两个节点之和+上一位的进位>9进位 原位变为(两个数之和+上一位的进位)%10,进位变为两个数之和+上一位的进位)/10 考虑边界情况: 1.只有在一个链表遍历指针不为空的情况下,才指向下一个 2.最末位进位,所以当进位为1的时候不能结束循环 */ struct ListNode* t1=l1;//遍历指针,不改变原来的链表 struct ListNode* t2=l2; struct ListNode* h3=(struct ListNode*)malloc(sizeof(struct ListNode));//头结点 struct ListNode* pNew=NULL;//指向新申请的节点 struct ListNode* pTail=h3;//指向链表的末尾 int sum=0; h3->val=0; h3->next=NULL;//初始化头结点 int carry=0;//向前一位的进位 while(t1||t2||carry) { pNew=(struct ListNode*)malloc(sizeof(struct ListNode));//申请新的节点 pNew->val=0; pNew->next=NULL;//申请新的节点,初始化该节点 int sum=0;//对应项的和 if(t1!=NULL)//只有在遍历指针不空的情况下才加上其值 { sum+=t1->val; } if(t2!=NULL) { sum+=t2->val; } sum+=carry; if(sum>=10) { sum=sum%10;//取模 carry=1;//进位 } else { carry=0;//取消进位 } pNew->val=sum; //将新的节点插入结果链表 pTail->next=pNew;//插入最新链表的末尾 pTail=pNew;//移动到尾节点 //向下遍历链表 if(t1!=NULL)//不空才指向下一个节点 { t1=t1->next; } if(t2!=NULL) { t2=t2->next; } } struct ListNode* temp2=h3->next; free(h3);//释放空的头结点 return temp2;//返回链表 }
画图分析
思路分析
整体上来说,如图所示一共有两个链表,其头结点分别是l1和l2。每一个链表的节点顺序是从头结点对应数字的低位,而尾节点对应数字的高位。我们的目的是将将两个链表按位相加,考虑进位的情况,最终得到一个新的链表,这个链表各个位对应两个链表对应数字相加的结果的各位结果。
如图,l1从高位到低位是1984,而l2从高位到低位是52。两个数字相加结果为2036,正好对应l3从高位到低位的2036.
然后我们分析一下过程,我们从低位到高位开始算,carry是进位。
* 0.初始进位为0,carray=0
* 4+2+carry=4+2+0=6 没有进位 carry=0;
* 8+5+carry=8+5+0=13 进了一位 carry=1; 值为 13%10=3
* 9+0+carry=9+0+1=10 进了一位 carry=1; 值为10%10=0
* 1+0+carry=1+0+1=2 进位为0
代码分析
1.为了尽可能简单,我们将创建一个新的链表来保存最终的结果,最后返回这个链表的头指针
2.在整个过程中不改变传入的两个链表
3.我们需要同时遍历两个链表
- 何时结束?两个条件缺一不可
- 两个链表都空的时候
- 进位为0的时候
4.每次都要申请一个新的节点
- 新的节点的值怎么算?如果对应两个节点的值+进位的值>9就取余数,否则就是两个节点的值+进位的值
- 进位怎么考虑?如果对应两个节点的值+进位的值>9进位为1,否则进位为0
- 还要考虑一个问题,如果某个链表的遍历指针指向空了怎么办?只有在遍历指针不指向空才加数值
5.插入新的链表,采用尾插法,这样才能对应顺序。
6.遍历指针后移,只有在遍历指针不为空的情况下才进行