两个长整数的相加

1.题目:两个非负整数以逆序形式存储在两个链表,计算他们的和并同样以逆序形式存进链表并返回。
在这里插入图片描述

我一开始的思路是把这两条链的数按位数乘10完整提出来,然后相加,再依次取位数对应数字存进链里,返回。
直到他给了我这么一个测试数据,我才明白它用链表传参的目的。
在这里插入图片描述
然后我搜了一下long long的取值范围:
-9223372036854775808-9223372036854775807
(即-2^63 - 2^63-1)
以及unsigned long: 0-1844674407370955161
(即0 - 2^64-1)

而这个测试数据起码有30位数!
所以完整提出来相加是不可能的了。

然后到第二个思路:
两个指针同时在对应的相同位置遍历两条链list1和list2,把当前遍历到的数拿出来相加,>=10则抛出进位数cnum=1,结果放到新增空间并尾插到新链,遍历继续。
在这里插入图片描述

这只是正常的情况,那么特殊的情况还有什么呢?
( [ ]内代表数字在链表里的顺序)

  1. 一长一短不进位:[0006]+[003]
    (6000+300)
  2. 一长一短进位到最后:[99]+[9999]
    (99+9999=10098)
  3. 一长一短进位,但中途结束:[99]+[24912]
    (99+21942=22041)
  4. 同长同短,但遍历的最后一组数会进位1:
    [5]+[5](5+5=10)

**对于一长一短的情况,我的思路是:
因为遍历条件是p和q同时不为NULL,此时的遍历已经断掉,但仍有p!=NULL或者q!=NULL。
(下面以p!=NULL为例子)
先定义新指针k,记录此时p的位置。

一.若此时进位数cnum为0:
将k直接连接到returnlist的尾端。

二.若此时进位数cnum为1:
则p继续遍历list剩下部分,每遍历一次抛出cnum的值,直到cnum等于0,遍历停止。
在此条件下(cnum为1),若遍历在最后一个数前停止,将k连接到returnlist的尾端;若在最后一个数的位置停止,则新增空间将其值设为1,连接到list1尾部,再将k连接到returnlist的尾端。

**同长同短,遍历最后一组数据进位1:
直接新增空间设置其值为1,连接到新链表尾部。

下面贴代码:
思路1(局限于长整型数据类型范围内):

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        long long x1 = 0, x2 = 0, count=1,ans = 0;
        ListNode* p;
        p = l1;                /*指向链1的第1个节点*/
        while (p != NULL) {       /*做循环,读取x1的值*/
            x1 += (p->val * count);
            p = p->next;
            count *= 10;
        }
        count = 1;  /*结束count置一*/
        p = l2;                /*指向链2的第1个节点*/
        while (p != NULL) {       /*做循环,读取x2的值*/
            x2 += (p->val * count);
            p = p->next;
            count *= 10;
        }
        ans = x1 + x2;
        long long tool = ans, flag = 0;
        do {                           /*整除法获取结果ans的位数*/
            tool =tool/10;
            flag++;
        } while (tool != 0);
        ListNode* answer = new ListNode;
        answer->next = NULL;
        count = 1;
        for (int i = 1; i < flag; i++) 
            count *= 10;          /*根据位数建立'取余法'的变量值*/
        for (int i = 0; i < flag; i++) {       /*将结果头插入链*/
            int part =ans / count;
            ans = ans - part * count;
            p = new ListNode;
            p->val = part;
            p->next = answer->next;
            answer->next = p;
            count /= 10;
        }
        answer=answer->next;
        return answer;
    }
};

思路一写了好久也想贴一下,原谅我的菜 ╮(╯﹏╰)╭

思路二(正确解法):

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
 class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* answer=new ListNode, * p = l1, * q = l2,*k=NULL,*o=NULL;
        answer->next = NULL;
        ListNode *New, * flag=answer;
        int ans = 0,judge=0;
        while (p != NULL && q != NULL) {     /*从链头到尾 对l1和l2每个对应节点做加法*/
            if (judge==1) {                  /*如果上两个数有进位,则加上1*/
                if ((p->val+q->val+judge)>=10) {
                    ans = (p->val + q->val+judge) % 10;
                    judge= 1;
                }
                if ((p->val + q->val+judge) < 10) {
                    ans = p->val + q->val+judge;
                    judge = 0;
                }
            }
           else {
                if ((p->val + q->val) >= 10) {
                    ans = (p->val + q->val) % 10;
                    judge = 1;
                }
                if ((p->val + q->val) < 10) {
                    ans = p->val + q->val;
                    judge = 0;
                }
            }
            
            New = new ListNode;
            New->val = ans;
            New->next = flag->next;  /*尾插法,flag->next永远是NULL*/
            flag->next = New;
            flag = flag->next;
            p = p->next; q = q->next;/*p,q遍历*/
        }
            if (p == NULL && q == NULL&&judge==1) {
            New = new ListNode;
            New->val = 1;
            New->next = NULL;
            flag->next = New;
        }
      if (p == NULL&&q!=NULL) { /*一长一短,q还没断*/
            k = q;
            if (judge == 0)flag->next = k;
            if (judge == 1) {
                while (q != NULL && judge == 1) {
                    if ((q->val + judge) >= 10) {
                        q->val = (q->val + judge) % 10;
                        judge = 1;
                    }
                    else {
                        q->val = q->val + judge;
                        judge = 0;
                    }
                    o = q;
                    q = q->next;
                }
                if (q == NULL && judge == 1) {
                    New = new ListNode;
                    New->val = 1;
                    New->next = NULL;
                    o->next = New;
                }
                flag->next = k;
            }
        }
        if (q == NULL && p != NULL) {/*一长一短,p还没断*/
             k = p;
            if (judge == 0)flag->next = k;
            if (judge == 1) {
                while (p != NULL && judge == 1) {
                    if ((p->val + judge) >= 10) {
                        p->val = (p->val + judge) % 10;
                        judge = 1;
                    }
                    else {
                        p->val = p->val + judge;
                        judge = 0;
                    }
                    o = p;
                    p = p->next;
                }
                if (p == NULL && judge == 1) {
                    New = new ListNode;
                    New->val = 1;
                    New->next = NULL;
                    o->next = New;
                }
                flag->next = k;
            }
        }
        answer = answer->next;/*去头(我个人认为去不去都可以)*/
        return answer;
    }
};

小结:
这个题目的思路对的话,再把每种情况想清楚就OK,运用一些简单的if和else语句,还有单链表的尾插法与头插法。
网上有更优的解法,轻喷。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莉妮可丝的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值