题目
给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
分析
本题目中需要重点考虑两点问题:
- 在执行加法运算的过程中可能会遇到进位,这个时候需要把进位的数字与不进位的数字分别处理
- 在两条链表都加结束时,可能还是需要进位,这样的情况下就需要新增节点存储进位
- 在链表的长度不一致的时候多余的节点被丢弃
这是定义的链表,使用pList指针类型维护链表
typedef int DataType;
typedef struct Node{
DataType data;
struct Node *next;
}Node, *pNode, List, *pList;
//初始化
void InitList(pList *ppl);
//尾部插入
void PushBack(pList *ppl, DataType d);
//打印链表
void PrintList(pList pl);
//链表加法
pList addTwoNumbers(pList list1, pList list2);
核心代码
pList addTwoNumbers(pList list1, pList list2)
{
pList newlist = NULL;
pNode newNode = NULL;
int flag = 0;//是否进位
int sum = 0;//两个data域之和
pNode tail = newlist;//维护尾插的指针
pNode cur = NULL;//寻找尾节点前一个节点的指针
//其中一条链表为空就直接返回NULL
if (list1 == NULL || list2 == NULL)
return NULL;
while (list1 != NULL && list2 != NULL)
{
sum = list1->data + list2->data;
if (flag)
sum++; //之前有进位则还要加1
//加了之后是否还需要进位的判断
if (sum >= 10)
flag = 1;
else
flag = 0;
//申请新节点
newNode = BuyNode(sum % 10);
//尾部插入(当然这里可以直接使用尾插的函数)
if (newlist == NULL)
{
newlist = newNode;
tail = newlist;
}
else
{
tail->next = newNode;
tail = tail->next;
}
//指针同时向后走
list1 = list1->next;
list2 = list2->next;
}
//如果加到最后还是需要进位的处理
if (flag == 1){
//printf("sum = %d\n", sum);
cur = newlist;
while (cur->next != NULL)
{
cur = cur->next;
}
cur->data = sum % 10;//修改最后一个元素
//追加进位的节点
newNode = BuyNode(1);
tail->next = newNode;
}
return newlist;
}
测试函数
void test()
{
pList plist1 = NULL;
pList plist2 = NULL;
pList newlist = NULL;
InitList(&plist1);
InitList(&plist2);
PushBack(&plist1, 2);
PushBack(&plist1, 4);
PushBack(&plist1, 3);
//PushBack(&plist1, 5); //测试最后进位新增节点
PushBack(&plist2, 5);
PushBack(&plist2, 6);
PushBack(&plist2, 4);
PrintList(plist1);
PrintList(plist2);
newlist = addTwoNumbers(plist1, plist2);
PrintList(newlist);
}
上面只是完成了基本操作,接下来才是重点
这个的测试用例实在是有点多,最后不得不画图做各种分析
自己优化后的代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
struct ListNode* newlist = NULL;
struct ListNode* newNode = NULL;
struct ListNode* tail = NULL;
int flag = 0;//是否进位
//其中一条链表为空就直接返回NULL
if (l1 == NULL || l2 == NULL)
{
return NULL;
}
while (l1 != NULL && l2 != NULL)
{
if ((l1->val + l2->val + flag) >= 10)
{
//PushBack(&newlist, (list1->data + list2->data + flag) % 10);
newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val = (l1->val + l2->val + flag) % 10;
newNode->next = NULL;
tail = newlist;
if (newlist == NULL)
{
newlist = newNode;
}
else
{
while (tail->next)
{
tail = tail->next;
}
tail->next = newNode;
}
flag = 1;
}
else
{
//PushBack(&newlist, list1->data + list2->data+ flag);
newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val = l1->val + l2->val + flag;
newNode->next = NULL;
tail = newlist;
if (newlist == NULL)
{
newlist = newNode;
}
else
{
while (tail->next)
{
tail = tail->next;
}
tail->next = newNode;
}
flag = 0;
}
l1 = l1->next;
l2 = l2->next;
}
//if (flag)
//{
// //PushBack(&newlist, 1);
// newNode = (pNode)malloc(sizeof(Node));
// newNode->data = 1;
// newNode->next = NULL;
// tail = newlist;
// if (newlist == NULL)
// newlist = newNode;
// else
// {
// while (tail->next)
// tail = tail->next;
// tail->next = newNode;
// }
//}
//开始处理多余部分
//printf("lis1t1 %d\n",list1->data);
while (l1 != NULL)
{
//使用指针找到链表的末尾
tail = newlist;
while (tail->next != NULL)
{
tail = tail->next;
}
//如果之前没有进位
if (flag == 0)
{
tail->next = l1;
return newlist;
}
//flag == 1
if (l1->val + 1 >= 10)
{
//PushBack(&newlist, (l1->val + 1) % 10);
newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val =(l1->val + 1) % 10;
newNode->next = NULL;
tail = newlist;
if (newlist == NULL)
{
newlist = newNode;
}
else
{
while (tail->next)
{
tail = tail->next;
}
tail->next = newNode;
}
flag = 1;
}
else
{
//PushBack(&newlist, l1->val + 1);
newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val = l1->val + 1;
newNode->next = NULL;
tail = newlist;
if (newlist == NULL)
{
newlist = newNode;
}
else
{
while (tail->next)
{
tail = tail->next;
}
tail->next = newNode;
}
flag = 0;
}
l1 = l1->next;
}
while (l2 != NULL)
{
//使用指针找到链表的末尾
tail = newlist;
while (tail->next != NULL)
{
tail = tail->next;
}
//如果之前没有进位
if (flag == 0)
{
tail->next = l2;
return newlist;
}
//flag == 1
if (l2->val + 1 >= 10)
{
//PushBack(&newlist, (l2->val + 1) % 10);
newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val = (l2->val + 1) % 10;
newNode->next = NULL;
tail = newlist;
if (newlist == NULL)
{
newlist = newNode;
}
else
{
while (tail->next)
{
tail = tail->next;
}
tail->next = newNode;
}
flag = 1;
}
else
{
//PushBack(&newlist, l2->val + 1);
newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val = l2->val + 1;
newNode->next = NULL;
tail = newlist;
if (newlist == NULL)
{
newlist = newNode;
}
else
{
while (tail->next)
{
tail = tail->next;
}
tail->next = newNode;
}
flag = 0;
}
l2 = l2->next;
}
//最后追加
if (flag == 1)
{
newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val = 1;
newNode->next = NULL;
tail = newlist;
if (newlist == NULL)
{
newlist = newNode;
}
else
{
while (tail->next)
{
tail = tail->next;
}
tail->next = newNode;
}
}
return newlist;
}
优化的代码
我自己的执行时间为24ms,但是接下来这种方式执行时间更快,为20ms
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
struct ListNode *head,*p,*q;
p=NULL;
q=NULL;
int sum=0,c=0;
while(l1!=NULL||l2!=NULL)
{
if(l1==NULL&&l2==NULL)
{
if(c==1)
{
p=(struct ListNode *)malloc(sizeof(struct ListNode));
if(p!=NULL)
{
p->val=c;
p->next=NULL;
if(q==NULL)
{
head=p;
q=p;
}
else
{
q->next=p;
q=p;
}
}
}
}
else if(l1!=NULL&&l2!=NULL)
{
sum=c+l1->val+l2->val;
c=sum/10;
p=(struct ListNode *)malloc(sizeof(struct ListNode));
if(p!=NULL)
{
p->val=sum%10;
p->next=NULL;
if(q==NULL)
{
head=p;
q=p;
}
else
{
q->next=p;
q=p;
}
}
}
else
{
sum=c+(l1!=NULL?l1->val:l2->val);
c=sum/10;
p=(struct ListNode *)malloc(sizeof(struct ListNode));
if(p!=NULL)
{
p->val=sum%10;
p->next=NULL;
if(q==NULL)
{
head=p;
q=p;
}
else
{
q->next=p;
q=p;
}
}
}
if(l1!=NULL)
l1=l1->next;
if(l2!=NULL)
l2=l2->next;
}
if(c==1)
{
p=(struct ListNode *)malloc(sizeof(struct ListNode));
if(p!=NULL)
{
p->val=c;
p->next=NULL;
if(q==NULL)
{
head=p;
q=p;
}
else
{
q->next=p;
q=p;
}
}
}
return head;
}