0
点赞
收藏
分享

微信扫一扫

LeetCode 2——两数相加(简单易想教程)

鱼板番茄 2022-03-19 阅读 53

思路:

用双指针同时记录两个链表,因为链表是逆序的,所以从头开始遍历正好符合我们加减法列算式的计算过程,两个数相加,只要大于等于10 则表示,有进位,我们只取%10,进位交给链表的下一个结点相加来处理。当至少有一个链表已经遍历完了,此时有三种情况:

1)l1遍历完,l2也遍历完,此时一定要注意我们在之前的运算中的carry(进位)是否为1,如果为1,说明还有进位没处理,要单独处理

2)l1遍历完,l2还未遍历完,仍然需要考虑carry是否已经被处理的问题

3)l1还未遍历完,l2已经遍历完,同上,需要carry考虑是否已经被处理的问题

话不多说,代码如下,要注意的地方有注释:

/**  链表结点的定义
 * 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* head = nullptr;
    ListNode* last = head;
    //如果两个链表都是0 则特别处理直接返回0
    if (l1->val==0&&l2->val==0&&l1->next==nullptr&&l2->next==nullptr) {
        return new ListNode(0);
    }
    ListNode* q1 = l1;
    ListNode* q2 = l2;
    int carry = 0;//记录是否有进位
    int cnt = 0;
    //双指针一直往后移 直到至少有一个链表已经遍历完
    while (q1 != nullptr && q2 != nullptr) {
        int num = q1->val + q2->val + carry;//这里的carry是上一次运算的进位,0或者1
        carry = 0;//这里必须要更新一下carry 因为 求num已经用过了carry
        if (num >= 10) {
            carry = 1;
            num = num % 10;//余数
        }
        if (cnt == 0) {
            ListNode* t = new ListNode(num);
            head = t;
            last = t;
            cnt = 1;
        }
        else {
            ListNode* t = new ListNode(num);
            last->next = t;
            last = t;
        }
        q1 = q1->next;
        q2 = q2->next;//往后移
    }
    //开始处理至少有一个链表遍历完的情况
    if (q1 == nullptr && q2 == nullptr) {
        if (carry == 1) last->next = new ListNode(1); //有可能有进位
    }
    else if (q1 == nullptr && q2 != nullptr) {
        if (carry == 1) {
            while (q2 != nullptr) {
                int num = q2->val + carry;
                carry = 0;
                if (num >= 10) {
                    carry = 1;
                    num = num % 10;
                }
                ListNode* t = new ListNode(num);
                last->next = t;
                last = t;
                q2 = q2->next;//后移
            }
            if (carry == 1) last->next = new ListNode(1);//这一条很容易漏 如果在链表最后一个数字为9并且有进位的时候 没有这一条会漏掉最后的1
        }
        else last->next = q2; //如果没有进位 则直接链上还未遍历完的链表
    }
    else {
        if (carry == 1) {
            while (q1 != nullptr) {
                int num = q1->val + carry;
                carry = 0;
                if (num >= 10) {
                    carry = 1;
                    num = num % 10;
                }
                ListNode* t = new ListNode(num);
                last->next = t;
                last = t;
                q1 = q1->next;//后移
            }
            if (carry == 1) last->next = new ListNode(1);//这一条很容易漏 如果在链表最后一个数字为9并且有进位的时候 没有这一条会漏掉最后的1
        }
        else last->next = q1;
    }
    return head;
}
};

 后面也试过了 先把每个链表转换成真实的数,然后相加之后,再把和通过不断除余转成链表,但很遗憾,用unsigned long long最后三个测试点仍然会数据溢出,要用数组存大数来处理。

举报

相关推荐

0 条评论