题目和解答思路源自于待字闺中微信。
题目:两个单链表,每一个节点里面一个0-9的数字, 输入就相当于两个大数了。然后返回这两个数的和(一个新list)。已知这两个输入的list 长度相等。 要求是:1. 不用递归。2. 要求算法在最好的情况下,只遍历两个list一次, 最差的情况下两遍。
个人分析:如果这两个链表是按照数的低位在前、高位在后排的,那么作加法没有难度,进位发生在后面。如果链表是按照高位在前排的,进位就比较麻烦。要怎么样进位呢?一个好的思想就是再引入一个pre指针,保存应该进位的位置。
两个个位数的和,最大的情况是18。
需要注意的是这三种情况:
1、如果和大于9,那么会对高位产生进位,且其和一定小于9(和小于9意味着属于第3种情况)。
2、如果和等于9,则下一位若有进位,则会使当前的9变为10,从而引发再进位。
3、如果和小于9,则不会产生进位,下一位的进位也不会引发再进位。
用来保存进位位置的pre指针会根据上面三种情况来向前移动。
由于最高位的进位可能会产生新的最高位(第n+1位),所以最高位的加法需要特殊考虑。
下面是实现代码。实现了只遍历两个list一次就得到相加结果。
# include<stdio.h>
# include<string.h>
# include<malloc.h>
typedef struct node{
int data;
node *next;
}node,*link;
void printlist(link a)
{
if(a==NULL)
printf("Error!\n");
while(a != NULL)
{
printf("%d", a->data);
a=a->next;
}
printf("\n");
}
link buildlist(int n)
{
link l;
int x;
node *tmp; //for create list
printf("Input list: ");
scanf("%d",&x);
l = (node *)malloc(sizeof(node));
l->data = x;
tmp = l;
for(int i=0;i<n-1;i++)
{
scanf("%d",&x);
tmp->next = (node *)malloc(sizeof(node));
tmp->next->data = x;
tmp = tmp->next;
}
tmp->next=NULL;
return l;
}
link addlist(link l1, link l2)
{
if(l1 == NULL || l2 == NULL)
return NULL;
link l3;
//pre指针存储进位的位置,p指针存储和的位置。
node *pre, *p;
node *p1=l1,*p2=l2;
//和链表的首个结点比较特殊
int sum = p1->data + p2->data;
if(sum>9)
{
//若最高位相加就要进位,则和链表开头是两个结点
l3 = (node *)malloc(sizeof(node));
l3->data = 1;
l3->next = (node *)malloc(sizeof(node));
l3->next->data = sum - 10;
pre = l3->next;
}
else
{
l3 = (node *)malloc(sizeof(node));
l3->data = sum;
pre = l3;
}
//设定p指针的初始位置
if(p1->next!=NULL && p2->next!=NULL)
{
p = (node *)malloc(sizeof(node));
pre->next = p;
p1 = p1->next;
p2 = p2->next;
}
else
{
pre->next = NULL;
return l3;
}
while(1)
{
sum = p1->data + p2->data;
//若要进位,p结点为和,pre结点进位++
if(sum>9)
{
p->data = sum-10;
pre->data += 1;
pre = pre->next;
while(pre->data==9)
{
pre->data = 0;
pre = pre->next;
}
}
else //若不进位,p结点为和,pre结点要判断是否移动
{
p->data = sum;
if(sum != 9)
pre = p;
}
p1 = p1->next;
p2 = p2->next;
if(p1!=NULL && p2!=NULL)
{
p->next = (node *)malloc(sizeof(node));
p = p->next;
}
else
{
p->next = NULL;
break;
}
}
//对最高位的10进行修正
if(l3->data == 10)
{
node *tmp = (node *)malloc(sizeof(node));
tmp->data = 1;
l3->data = 0;
tmp->next = l3;
l3 = tmp;
}
return l3;
}
int main()
{
int n=5;
link l1 = buildlist(n);
link l2 = buildlist(n);
link l3 = addlist(l1, l2);
printlist(l3);
return 1;
}