力扣-2-两数相加

一、题目理解

题目描述

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

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

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

示例

输入:l1 = [2,4,3], l2 = [5,6,4]

输出:[7,0,8]

解释:342 + 465 = 807,逆序存储后结果为 [7,0,8]。

二、解题思路

这道题的核心是模拟手工加法的过程,关键点如下:

  1. 两个链表逆序存储数字,正好符合"从个位开始相加"的加法逻辑;
  2. 相加时需要处理进位(进位值只能是 0 或 1,因为两个个位数相加最大是 9+9=18,进位1);
  3. 两个链表长度可能不同,需要处理"短链表遍历完但长链表还有剩余"的情况;
  4. 最后如果还有进位(比如 999 + 1 = 1000),需要额外新增一个节点存储进位。

三、Java代码实现

首先定义题目中的链表节点类(力扣会默认提供,无需自己写),然后实现核心逻辑:

java 复制代码
// 链表节点定义(力扣题目中已给出)
class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        // 虚拟头节点(简化链表操作,避免处理头节点为空的情况)
        ListNode dummyHead = new ListNode(0);
        // 遍历指针,用于构建结果链表
        ListNode curr = dummyHead;
        // 进位值,初始为0
        int carry = 0;
        
        // 循环条件:l1未遍历完 或 l2未遍历完 或 还有进位
        while (l1 != null || l2 != null || carry != 0) {
            // 取出当前节点的值,若节点为空则取0
            int val1 = (l1 != null) ? l1.val : 0;
            int val2 = (l2 != null) ? l2.val : 0;
            
            // 计算当前位的和(包含进位)
            int sum = val1 + val2 + carry;
            // 当前位的结果:和对10取余
            int currentVal = sum % 10;
            // 更新进位:和除以10取整(只能是0或1)
            carry = sum / 10;
            
            // 创建新节点,加入结果链表
            curr.next = new ListNode(currentVal);
            // 指针后移
            curr = curr.next;
            
            // 原链表指针后移(非空时)
            if (l1 != null) l1 = l1.next;
            if (l2 != null) l2 = l2.next;
        }
        
        // 虚拟头节点的下一个节点才是结果链表的头
        return dummyHead.next;
    }
}

四、代码关键解析

  1. 虚拟头节点(dummyHead)

    • 为什么用?如果直接用真实头节点,需要额外判断"结果链表是否为空",虚拟头节点可以统一处理所有节点的添加逻辑,最后返回 dummyHead.next 即可。
    • 比如示例中,先创建 dummyHead(0),然后依次添加 7、0、8,最终返回 dummyHead.next 就是 [7,0,8]。
  2. 循环条件

    • l1 != null || l2 != null || carry != 0:覆盖三种情况:
      • l1还有节点未遍历;
      • l2还有节点未遍历;
      • 两个链表都遍历完,但最后一位相加有进位(如 999 + 1 = 1000)。
  3. 数值处理

    • val1 = l1 != null ? l1.val : 0:短链表遍历完后,后续位用 0 补充(比如 l1=[2,4], l2=[5,6,4],则 l1 的第三位视为 0);
    • sum = val1 + val2 + carry:必须加上上一位的进位;
    • currentVal = sum % 10:取当前位的结果(如 4+6=10,当前位是 0);
    • carry = sum / 10:更新进位(如 4+6=10,进位是 1)。
  4. 指针移动

    • 结果链表的指针 curr 每次后移,指向新创建的节点;
    • 原链表的指针 l1/l2 只有非空时才后移,避免空指针异常。

五、测试示例

l1 = [2,4,3], l2 = [5,6,4] 为例,执行过程:

步骤 val1 val2 carry sum currentVal 结果链表(curr指向)
1 2 5 0 7 7 dummyHead -> 7
2 4 6 0 10 0 dummyHead -> 7 -> 0
3 3 4 1 8 8 dummyHead -> 7 -> 0 -> 8
4 0 0 0 0 - 循环结束
最终返回 dummyHead.next 即 [7,0,8],符合预期。

总结

  1. 核心逻辑:模拟手工加法,从个位(链表头)开始相加,处理进位和链表长度不一致的问题;
  2. 关键技巧:使用虚拟头节点简化链表操作,循环条件覆盖"链表未遍历完"和"最后有进位"两种场景;
  3. 边界处理:短链表补 0、最后进位新增节点,避免空指针异常。

这道题是链表的入门经典题,掌握后能理解链表遍历、虚拟头节点、进位处理等核心考点,后续可以尝试优化空间(比如直接在原链表上修改),但上述解法是最易理解、面试中最推荐的写法。

相关推荐
寻寻觅觅☆11 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
偷吃的耗子12 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
化学在逃硬闯CS13 小时前
Leetcode1382. 将二叉搜索树变平衡
数据结构·算法
ceclar12313 小时前
C++使用format
开发语言·c++·算法
Gofarlic_OMS13 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
夏鹏今天学习了吗14 小时前
【LeetCode热题100(100/100)】数据流的中位数
算法·leetcode·职场和发展
忙什么果14 小时前
上位机、下位机、FPGA、算法放在哪层合适?
算法·fpga开发
董董灿是个攻城狮14 小时前
AI 视觉连载4:YUV 的图像表示
算法
ArturiaZ15 小时前
【day24】
c++·算法·图论
大江东去浪淘尽千古风流人物16 小时前
【SLAM】Hydra-Foundations 层次化空间感知:机器人如何像人类一样理解3D环境
深度学习·算法·3d·机器人·概率论·slam