LeetCode 2 — 两数相加(Add Two Numbers) 笔记

1. 题目描述

给定两个非空链表 l1 和 l2,它们表示两个非负整数。数字以 逆序 方式存储,每个节点只存储一位数字。请将两个数相加,并以相同形式返回一个表示和的链表。

示例:

输入:l1 = [2 -> 4 -> 3],  l2 = [5 -> 6 -> 4]
输出:[7 -> 0 -> 8]    // 342 + 465 = 807

2. 虚拟头节点(dummy)的作用

使用一个 栈上dummy 节点,可以简化链表构造:

ListNode dummy(0);
ListNode* cur = &dummy;
  1. 统一插入逻辑:无需区分第一个节点和后续节点,所有插入都用 cur->next = ...
  2. 简化返回:最终结果链表头为 dummy.next,无须额外空指针判断。
  3. 避免空指针dummy 永远存在,cur 始终有效。
  4. 自动回收dummy 在函数结束时自动销毁,无需 delete

3. 栈上 vs 堆上 分配

写法 存储位置 生命周期 释放方式
ListNode dummy(0); 栈(stack) 作用域结束自动销毁 自动
new ListNode(val) 堆(heap) 跨函数、直到显式 delete 手动 delete 或 OS 回收

4. ListNode vs ListNode* 何时使用

原则

需要跨函数传递或动态控制节点数,使用堆分配和指针;仅本地临时使用,使用栈对象。


5. 代码实现与修正

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(0);
        ListNode* cur = &dummy;
        int carry = 0;

        // 核心:使用 while 而非 if,处理所有节点和进位
        while (l1 || l2 || carry) {
            int sum = carry;
            if (l1) {
                sum += l1->val;
                l1 = l1->next;
            }
            if (l2) {
                sum += l2->val;
                l2 = l2->next;
            }

            carry = sum / 10;
            cur->next = new ListNode(sum % 10);
            cur = cur->next;
        }

        return dummy.next;
    }
};

修正要点


以上内容即本题核心思路与实现要点。

6. 输入输出格式

输入:两个链表头指针 l1 和 l2,分别表示两个逆序存放的非负整数的位序列。

例如:l1 = [2,4,3] 对应数字 342; l2 = [5,6,4] 对应数字 465。

输出:返回一个链表头指针,指向表示两数之和的逆序链表。

对应上例,输出链表为 [7,0,8],表示数字 807。

代码模板:

#include <bits/stdc++.h>
using namespace std;

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

// 从向量创建链表(逆序)
ListNode* createList(const vector<int>& v) {
    ListNode dummy(0);
    ListNode* cur = &dummy;
    for (int x : v) {
        cur->next = new ListNode(x);
        cur = cur->next;
    }
    return dummy.next;
}

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode dummy(0);
        ListNode* cur = &dummy;
        int carry = 0;
        while (l1 || l2 || carry) {
            int sum = carry;
            if (l1) { sum += l1->val; l1 = l1->next; }
            if (l2) { sum += l2->val; l2 = l2->next; }
            carry = sum / 10;
            cur->next = new ListNode(sum % 10);
            cur = cur->next;
        }
        return dummy.next;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n1;
    cin >> n1;
    vector<int> v1(n1);
    for (int i = 0; i < n1; ++i) cin >> v1[i];

    int n2;
    cin >> n2;
    vector<int> v2(n2);
    for (int i = 0; i < n2; ++i) cin >> v2[i];

    ListNode* l1 = createList(v1);
    ListNode* l2 = createList(v2);

    Solution sol;
    ListNode* res = sol.addTwoNumbers(l1, l2);

    // 输出结果
    bool first = true;
    while (res) {
        if (!first) cout << ' ';
        first = false;
        cout << res->val;
        res = res->next;
    }
    cout << '
';
    return 0;
}