Problems:
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
题目是给定两个链表,代表两个非负整数。整数上的数字逆序存储,每一个节点包括一个数字,使这两个整数相加,然后用链表返回。
思路:
-
实际上就是一个设计一个类似加法器的东西,用链表的数据结构来实现。
-
加法器的基本思路要了解,进位带着走。
-
需要考虑两个链表长度不一致的情况
- len<min(len1,len2),公共部分的加法
- 当遍历完短链表时,注意加法的加数减少一项
- 全都遍历之后,若有进位,最高位记得新开结点去存放
C语言代码:
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
struct ListNode* tmp1;
struct ListNode* tmp2;
struct ListNode* tmp3; //链表结点索引
struct ListNode* l3 = NULL;//一开始第三个链表为空,l3链表头指针
int carry=0;
if(l1==NULL||l2==NULL)//有链表为空的话直接返回
{
return (l1==NULL?l2:l1);
}
tmp1=l1; //索引
tmp2=l2;
tmp3=l3;
while(tmp1!=NULL&&tmp2!=NULL)//处理公共部分
{
struct ListNode* newnode= (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = (tmp1->val + tmp2->val + carry)%10;
newnode->next = NULL;
carry = (tmp1->val + tmp2->val + carry)/10;
if(l3==NULL)//如果开始链表为空,那么就填充值
{
l3 = tmp3 = newnode;
}
else//如果不空,直接将newnode接在后面
{
tmp3->next = newnode;
tmp3 = tmp3->next;// tmp3始终指向链表末尾
}
tmp1 = tmp1->next;
tmp2 = tmp2->next;
}
if(tmp1==NULL)//如果第一个链表遍历完了
{
while(tmp2!=NULL)
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = (carry + tmp2->val)%10;
newnode->next = NULL;
carry = (carry + tmp2->val)/10;
tmp3->next = newnode;
tmp3 = tmp3->next; // tmp3移到里l3链表末尾
tmp2 = tmp2->next;
}
if(carry!=0) // 最高位还有进位
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = (carry)%10;
newnode->next = NULL;
tmp3->next = newnode;
newnode->next = NULL;
}
}
if(tmp2==NULL)//如果第一个链表遍历完了
{
while(tmp1!=NULL)
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = (carry + tmp1->val)%10;
newnode->next = NULL;
carry = (carry + tmp1->val)/10;
tmp3->next = newnode;
tmp3 = tmp3->next; // tmp3移到里l3链表末尾
tmp1 = tmp1->next;
}
if(carry!=0) // 最高位还有进位
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = (carry)%10;
newnode->next = NULL;
tmp3->next = newnode;
}
}
return l3;
}
注意点
- 如何新建结点?
- 结构体指针变量和结构体变量对于成员的引用方式?( . 和 -> )
- 加法器设计,
value = (carry + add1 + add2 )% 10; carry = (carry + add1 + add2 ) /10
- 关于新建链表的问题:
- 新建链表的标准做法是新建头结点分配结点空间,置next为NULL,然后再用头插法、尾插法来构建链表。但是做题目时候注意返回的指针是头结点后一个有值的结点。
- 上面这种方法没有标准头结点,链表的第一个结点即有值,所以需要多加一个if判断该结点是否为开始结点。