LeetCode:两数相加

题目:
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 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 对进位结点进行处理,每次都新建。 那原有的进位结点未处理会有一定内存泄露

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值