1、题目
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2、分析
从题目可以看出,两个链表按位相加,存放在新的链表中,最后倒序输出,即可以得到需要的值,,需要特别注意进位的实现。
3、实现
代码
// 链表结构
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
// 两数相加
ListNode* AddTwoNums(ListNode* l1, ListNode* l2)
{
ListNode* list = NULL;
ListNode* temp = NULL;
// 两数相加,如果大于10,保存进位值。
int intNum = 0;
if (l1 == NULL && l2 == NULL)
{
return list;
}
list = new ListNode(0);
temp = list;
while (l1 != NULL || l2 != NULL)
{
int intA = (l1 != NULL) ? l1->val : 0;
int intB = (l2 != NULL) ? l2->val : 0;
int sum = intA + intB + intNum;
// 如果当前结果大于10 ,求出进位。
intNum = sum / 10;
// 取余求出当前位的值,保存在新节点
temp->next = new ListNode(sum % 10);
temp = temp->next;
if (l1 != NULL)
{
l1 = l1->next;
}
if (l2 != NULL)
{
l2 = l2->next;
}
}
if (intNum > 0)
{
// 最后进位,添加新节点
temp->next = new ListNode(intNum);
}
return list->next;
}
测试用例
int main()
{
ListNode* l1 = new ListNode(4);
ListNode* curr = l1;
curr->next = new ListNode(0);
curr = curr->next;
curr->next = new ListNode(4);
ListNode* l2 = new ListNode(4);
curr = l2;
curr->next = new ListNode(5);
curr = curr->next;
curr->next = new ListNode(6);
// 计算4→0→4 + 4→5→6 ,结果为 8→5→0→1 则为正确。
// 即 404+654=1058
ListNode* re = AddTwoNums(l1, l2);
while (re!=NULL)
{
cout << re->val;
re = re->next;
}
cout << endl;
system("pause");
return 0;
}
测试结果
4、扩展
问题
有朋友问我,如果对原来的题目进行扩展,要求在原来的基础上,返回值以正序方式存储。应该怎么实现呢?
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:243 + 564 = 807
分析
在逆序输出时,我们返回链表的next域,即list->next,这样方便进位。同样,如果我们直接返回链表的本体list,则可以利用本体的val字段,将进位放在当前域即可。至于如何实现,小伙伴们可以先试试,后续我会将代码实现和测试用例等一并同步。正文中实现的算法,相信各位小伙伴们都能实现,如果有更好更优的想法,可以留言或者私信我,不胜感激。如果你也在学习算法,请关注我,一起学习,共同进步!