题目:
You are given two linked lists representing two non-negative numbers. 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.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
题意解析:
题目就是将两个链表对应位的数目进行相加,但如果超过十的话,需要进1,跟整数的加法一样,只是每个结点存储1位。
题目很简单,并且看到样例更会受到误导。需要先考察链表L1和链表L2的长度,哪一个比较长。当最后一位相加后再产生进位,也要单独处理。还有,我们建立链表的时候是在表头插入还是在表尾插入等等。这些方面都要考虑。
方案一:
这个是我的方法,将L2的数据加到L1上,当L2的长度比L1长的话,将多出的结点链接到L1上。(这里就导致一个问题,当我们最后销毁两个链表的时候,L2和L1有了公共结点,会导致系统崩溃。需要额外处理,不过我没有加上这段代码,只是设置q的父节点,当L2后续结点链接到L1后,将q的父节点的next指针设为空即可。)最末尾的时候,要单独处理一下进位。
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
LinkList InitList(void)
{
LinkList head = (LinkList)malloc(sizeof(LNode));
if(head == NULL){
printf("Memory allocation failure!\n");
exit(1);
}
head->next = NULL;
return head;
}
void CreateList(LinkList head,int data)
{
LinkList p = (LinkList)malloc(sizeof(LNode));
if(!p){
printf("Memory allocation failure!\n");
exit(1);
}
p->data = data;
p->next = head->next;
head->next = p;
}
void AddList(LinkList dest,LinkList src)
{
LinkList p,q,parent;
int carryover = 0;
if(!dest || !src){
printf("NULL!");
exit(1);
}
parent = dest;
p = parent->next;
q = src->next;
while(p && q){
p->data += q->data + carryover;
carryover = p->data / 10;
p->data %= 10;
parent = p;
p = parent->next;
q = q->next;
}
if(q) // q->length > p->length
parent->next = q;
q = parent->next; //将q->length > p->length统一到q->length < p->length上
while(carryover && q){ //如果进位存在,并且q不为空指针的时候,将carryover加到q->data上
q->data += carryover;
carryover = q->data / 10;
q->data %= 10;
parent = q;
q = q->next;
}
if(carryover){ //单独处理进位
LinkList Q = (LinkList)malloc(sizeof(LNode));
if(!Q)
exit(1);
Q->data = carryover;
Q->next = NULL;
parent->next = Q;
}
}
void PrintList(LinkList head)
{
LinkList p = head->next;
while(p){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
void DestoryList(LinkList head)
{
LinkList p = head->next,q;
head->next = NULL;
while(p){
q = p->next;
free(p);
p = q;
}
}
int main(void)
{
int n,m,data;
LinkList dest,src;
dest = InitList();
src = InitList();
printf("input how many numbers of n and m:");
while(scanf("%d %d",&n,&m) == 2){
printf("input the n+m datas:");
for(int i = 0;i < n;++i){
scanf("%d",&data);
CreateList(dest,data);
}
for(int i = 0;i < m;++i){
scanf("%d",&data);
CreateList(src,data);
}
AddList(dest,src);
PrintList(dest);
printf("input how many numbers of n and m:");
}
return 0;
}
方案二:
如果这个题目,创建第三方链表会更方便,并且将L1->data 、L2->data和carryover三个数相加,分两次进行,会简化思路,得到更好的效果。下面这段代码摘自网络,很值得学习!
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
ListNode* ret = NULL;
ListNode** cur = &ret;
int carry = 0;
int sum = 0;
while(l1 != NULL || l2 != NULL)
{
sum = carry;
if(l1 != NULL)
{
sum += l1->val;
l1 = l1->next;
}
if(l2 != NULL)
{
sum += l2->val;
l2 = l2->next;
}
carry = sum/10;
sum %= 10;
*cur = new ListNode(sum);
cur = &(*cur)->next;
}
if(carry > 0)
*cur = new ListNode(carry);
return ret;
}
};