Desciption
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.
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
Example
Input:
(2 -> 4 -> 3) + (5 -> 6 -> 4)
Output:
7 -> 0 -> 8
Explanation:
342 + 465 = 807.
Solution 1:
思路:直接从两个链表所表示数的个位加起(即两个链表同时从前往后遍历),逐位计算,并赋值给结果链表,直到一个遍历到尾。再单独处理另一个未到尾部的链表,难点在于进位的处理。尤其最后一位不能忘;还有就是链表的操作要熟练掌握!
#include <iostream>
#include <string>
#include <cstdlib> // free(), malloc()
#include <cstdio> // getchar()
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
if (!l1) // 如果一个为空,直接返回另一个
return l2;
else if (!l2)
return l1;
else
{
ListNode *res = NULL;
ListNode *p1, *p2, *p3, *pre;
p3 = res;
p1 = l1;
p2 = l2;
int flag = 0; // 进位标志
while (p1 != NULL && p2 != NULL)
{
p3 = new ListNode(0);
if (res == NULL)
res = p3;
else
pre->next = p3;
p3->next = NULL;
pre = p3;
if (p1->val + p2->val + flag < 10)
{
p3->val = p1->val + p2->val + flag;
flag = 0;
}
else
{
p3->val = p1->val + p2->val + flag - 10;
flag = 1;
}
p1 = p1->next;
p2 = p2->next;
}
while (p1) // 进入此循环表示此时 l2 部分已运算完,l1未完
{
p3 = new ListNode(0);
pre->next = p3;
p3->next = NULL;
pre = p3;
if (p1->val + flag < 10)
{
p3->val = p1->val + flag;
flag = 0;
}
else
{
p3->val = p1->val + flag - 10;
flag = 1;
}
p1 = p1->next;
}
while (p2) // 进入此循环表示此时 l1 部分已运算完,l2未完
{
p3 = new ListNode(0);
pre->next = p3;
p3->next = NULL;
pre = p3;
if (p2->val + flag < 10)
{
p3->val = p2->val + flag;
flag = 0;
}
else
{
p3->val = p2->val + flag - 10;
flag = 1;
}
p2 = p2->next;
}
if (flag) // 判断最后一位是否进位
{
p3 = new ListNode(0);
pre->next = p3;
p3->next = NULL;
pre = p3;
p3->val = flag;
}
return res;
}
}
/* 主函数,用来测试,输入时第一行输入 l1 各节点数据,空格隔开,回车结束输入,第二行输入 l2 各节点数据 */
int main(void)
{
ListNode *l1 = NULL;
ListNode *l2 = NULL;
ListNode *pre, *current;
while (1) // 逐位输入l1,以换行结束
{
current = new ListNode(0);
if (l1 == NULL)
l1 = current;
else
pre->next = current;
current->next = NULL;
pre = current;
cin >> current->val;
if (getchar() == '\n')
break;
}
pre = NULL;
current = NULL;
while (1) // 逐位输入l2,以换行结束
{
current = new ListNode(0);
if (l2 == NULL)
l2 = current;
else
pre->next = current;
current->next = NULL;
pre = current;
cin >> current->val;
if (getchar() == '\n')
break;
}
ListNode *res = addTwoNumbers(l1, l2);
current = res;
while (current) // 输出结果
{
cout << current->val << " ";
current = current->next;
}
cout << endl;
current = l1; // 释放 l1
while (current)
{
current = l1->next;
free(l1);
l1 = current;
}
current = l2; // 释放 l2
while (current)
{
current = l2->next;
free(l2);
l2 = current;
}
current = res; // 释放 res
while (current)
{
current = res->next;
free(res);
res = current;
}
return 0;
}
结果:
个人感觉海星吧。
Solution 2:最简洁
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2)
{
ListNode preHead(0), *p = &preHead;
int extra = 0;
while (l1 || l2 || extra)
{
int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + extra;
extra = sum / 10; // 进位
p->next = new ListNode(sum % 10);
p = p->next;
l1 = l1 ? l1->next : l1;
l2 = l2 ? l2->next : l2;
}
return preHead.next;
}
太tm强了。。。。最简洁(但复杂度非最优)的答案。
思路:其实跟上面我的代码是一个思路,,,但是这段代码巧妙运用三元运算符
及(l1 || l2 || extra)
的关系,将整个计算过程统一起来。复杂度和 Solution 1 一样。
当然,如果想要更好的空间复杂度,则可以尽量用
l
1
,
l
2
l1,l2
l1,l2 中某个链表来存结果,这样便可节省许多空间!