Leetcode力扣解题记录--第2题(加法模拟)

题目链接:2. 两数相加 - 力扣(LeetCode)

题目描述

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

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

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

示例 1:

输入: l1 = 2,4,3, l2 = 5,6,4
输出: 7,0,8
**解释:**342 + 465 = 807.

示例 2:

输入: l1 = 0, l2 = 0
输出:0

示例 3:

输入: l1 = 9,9,9,9,9,9,9, l2 = 9,9,9,9
输出:8,9,9,9,0,0,0,1

题目作答

这个问题的核心是模拟我们上小学时学习的竖式加法。由于链表中的数字是逆序存储的,这恰好为我们从最低位(个位)开始相加提供了便利,与手动计算的方向完全一致。

整体思路如下:

  1. 同步遍历:我们同时从两个链表的头节点(即数字的最低位)开始遍历。

  2. 逐位相加:在每一步中,我们将两个链表当前节点的值与上一步产生的**进位(carry)**相加。

    • 当前位总和 = l1当前节点值 + l2当前节点值 + carry
  3. 计算新节点值和新进位

    • 放入新链表中的节点值应该是总和的个位数,即 当前位总和 % 10。

    • 新的进位则是总和的十位数,即 当前位总和 / 10,这个进位会用于下一位的计算。

  4. 构建新链表:我们创建一个新的链表来存储结果。为了方便操作,我们可以使用一个"哑节点"(dummy head)作为新链表的伪头节点,并用一个 current 指针来追踪新链表的尾部,以便于添加新节点。

  5. 处理长短不一和最后进位

    • 如果一个链表比另一个长,当短的链表遍历结束后,我们视其为空,其节点值为0,继续与长链表的剩余部分和进位相加。

    • 遍历的循环条件应该是两个链表都不为空,或者进位不为0。这确保了在两个链表都遍历完后,如果还有一个最后的进位(例如 99 + 1 = 100),我们能把这个进位 1 作为最高位添加到结果链表中。

通过这个过程,我们就能完整地模拟两个逆序数字的相加,并生成一个符合要求的结果链表。

cpp 复制代码
/**
 * 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* dummyHead = new ListNode(0);
        ListNode* current = dummyHead;
        
        // carry 用于存储进位
        int carry = 0;
        
        // 循环条件:只要l1或l2没有遍历完,或者还有进位,就继续
        while (l1 != nullptr || l2 != nullptr || carry != 0) {
            // 获取l1和l2当前节点的值,如果节点为空则视为0
            int val1 = (l1 != nullptr) ? l1->val : 0;
            int val2 = (l2 != nullptr) ? l2->val : 0;
            
            // 计算当前位的总和
            int sum = val1 + val2 + carry;
            
            // 更新进位,为下一次计算做准备
            carry = sum / 10;
            
            // 创建新节点,值为总和的个位数,并链接到结果链表
            current->next = new ListNode(sum % 10);
            
            // 移动current指针到新链表的尾部
            current = current->next;
            
            // 移动l1和l2的指针
            if (l1 != nullptr) {
                l1 = l1->next;
            }
            if (l2 != nullptr) {
                l2 = l2->next;
            }
        }
        
        // 哑节点的下一个节点是结果链表的真正头节点
        ListNode* resultHead = dummyHead->next;
        delete dummyHead; // 释放哑节点的内存
        return resultHead;
    }
};
相关推荐
J-Tony117 小时前
【JVM】三色标记法
java·jvm·算法
wengad7 小时前
机器学习实践理论基础|算法、模型和数据集
人工智能·算法·机器学习
Titan20247 小时前
Linux动静态库
linux·服务器·c++
j_xxx404_8 小时前
MySQL表操作硬核解析:从 CREATE TABLE 到磁盘文件、ALTER TABLE 与 DDL 风险
运维·服务器·数据库·c++·mysql·adb·ai
wuminyu8 小时前
Java锁机制之park和unpark源码剖析
java·linux·c语言·jvm·c++
梦梦代码精8 小时前
为什么这个开源的AI平台会火?有点东西。。。
人工智能·算法·机器学习·docker·开源
随意起个昵称9 小时前
线性dp-综合刷题1(Not Alone)
算法·动态规划
玖玥拾9 小时前
C/C++ 基础笔记(十一)类的进阶
c语言·c++·设计模式·
-森屿安年-9 小时前
1137. 第 N 个泰波那契数
c++·动态规划
Lyyaoo.10 小时前
【数据结构】HashMap底层存储+扩容机制+线程安全【待更新】
数据结构·安全·哈希算法