Leetcode 2. 两数相加

289 阅读2分钟

原题链接: 2. 两数相加 - 力扣(Leetcode)

tag: 链表.

一. 题目

给你两个 非空 的链表, 表示两个非负的整数. 它们每位数字都是按照 逆序 的方式存储的, 并且每个节点只能存储 一位 数字.

请你将两个数相加, 并以相同形式返回一个表示和的链表.

你可以假设除了数字 0 之外, 这两个数都不会以 0 开头.

二. 题解

本题我们通过将两个链表的节点相加后再 尾插 到表示加的链表中来对两个链表进行相加.

由于尾插第一个节点时表示加的链表中没有节点, 即 tail == nullptr, 无法通过 tail->next = new ListNode(carry % 10); 来尾插相加后的节点, 需要分类讨论.

为了避免这种额外的讨论, 我们引入虚拟头节点(dummy)的概念.

设置虚拟头节点, 即在链表的头节点前新插入一个节点. 如此, 链表的头节点便有了前驱节点(即dummy), 尾插时就不需要进行额外的讨论.

image.png

ListNode* dummy = new ListNode(), * tail = dummy;

image.png

int carry = 0;

image.png

当 l1 不为空 或者 l2 不为空 或者 进位 carry 不为 0 时, 循环迭代.

l1 != nullptr;

image.png

carry += l1->val;

image.png

l1 = l1->next; 更新 l1 指针.

image.png

l2 != nullptr;

image.png

carry += l2->val;

image.png

l2 = l2->next; 更新 l2 指针.

image.png

tail->next = new ListNode(carry % 10); 将新节点尾插到 dummy 后面.

image.png

tail = tail->next; 更新 tail 指针.

image.png

carry /= 10; carry 进位.

image.png

重复这一步骤, 直到 while 循环终止.

image.png

ListNode* head = dummy->next;

image.png

delete dummy;

image.png

return head; 返回新链表的头节点.

image.png

三. 复杂度分析

时间复杂度: O(max(M, N)), 其中 M 和 N 分别表示两个链表的长度.

空间复杂度: O(1).

四. 代码

/**
 * 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* dummy = new ListNode(), * tail = dummy;    // 创造一个虚拟头节点 dummy 用来尾插新节点
        int carry = 0;    // carry 表示当前位的值
        while (l1 || l2 || carry) {    // 从低位到高位遍历两个非负整数
            if (l1) {
                carry += l1->val;
                l1 = l1->next;    // 更新 l1 指针
            }
            if (l2) {
                carry += l2->val;
                l2 = l2->next;    // 更新 l2 指针
            }
            tail->next = new ListNode(carry % 10);    // 将新节点尾插到 dummy 后面
            tail = tail->next;    // 更新 tail 指针
            carry /= 10;    // carry 进位
        }
        ListNode* head = dummy->next;    // 返回新链表的头节点       
        delete dummy;
        return head;
    }
};