题目:
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
解题思路:
整数存放和结果存放都是逆序存放的,正好可以边遍历边计算并插入链表。
计算过程:从头开始遍历,
每次取出两个表中相应位的数字, / 获得进位信息, % 获得本位信息。
建立链表节点,插入链表中。
进位信息正好用在下一次计算中。
但此处的下一次计算也是一个小bug点。
对于个位数相加 如[5 ,5] ,结果应该是[ 0 ,1 ].如果不在本次计算中把进位结果插入链表中,则会输出[ 0] 而导致错误。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int bit=0,sum=0;
int a1=0,a2=0;
ListNode *ret = new ListNode(0);
ListNode *tmp = ret;
while(l1!=NULL || l2!=NULL)
{
if(l1!=NULL)
{
a1=l1->val;
l1=l1->next;
}
else
{
a1=0;
}
if(l2!=NULL)
{
a2=l2->val;
l2=l2->next;
}
else
{
a2=0;
}
if(tmp->next!=NULL) //有无进位要提前建立结点,此处做判断分情况处理
{
sum = a1+a2+1;
bit = sum/10;
sum = sum%10;
tmp->next->val =sum; //因为之前有进位,结点已经建立,所以此处是修改值,而不是新建结点
}
else
{
sum = a1+a2;
bit = sum/10;
sum = sum%10;
tmp->next=new ListNode(sum);
}
tmp=tmp->next;
if(bit)
{
tmp->next=new ListNode(1); //如果有进位信息,要在当前处理,建立结点。不能留在下一次
//tmp=tmp->next;
bit=0;
}
}
ret=ret->next; //因为建立的头结点val是0,所以这里要移到第二个结点
return ret;
}
};
运行结果:
执行结果:
通过
执行用时 :
24 ms, 在所有 C++ 提交中击败了98.37%的用户
内存消耗 :
10.3 MB, 在所有 C++ 提交中击败了85.09%的用户
————————————————————————————————
本例中,我犯的最多的错误是在链表的next遍历中。
第一处
while(l1!=NULL || l2!=NULL)
因为在循环体中有
l1=l1->next;
所以条件判断时不能判断 l1->next ! = NULL ,这样会导致循环结束最后一位无法参与计算。(因为 L1当前指向末位,它的next域确实是NULL)
第二处:
ret=ret->next;
将这个语句放在了循环体中,这样遍历结束后丢掉了前面结点的信息。
所以正确的是
tmp=tmp->next; 用临时变量来遍历,ret保存头结点信息
官方题解中,思路一样,但是代码上用了三目运算符等,更简练一些
while (p != null || q != null) {
int x = (p != null) ? p.val : 0;
int y = (q != null) ? q.val : 0;
int sum = carry + x + y;
carry = sum / 10;
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p != null) p = p.next;
if (q != null) q = q.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
但是它这里并没有通过 if 对进位结点进行处理,每次都新建。 那原有的进位结点未处理会有一定内存泄露