[力扣]给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点[leetcode 002]

2.两数相加:链表题解与分析

题目描述

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

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

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

题目002

示例 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. 处理进位(sum = val1 + val2 + carry)
  3. 构建新的链表存储结果

步骤分解

  1. 初始化:创建一个哑节点(dummy node)作为结果链表的起点
  2. 遍历链表:同时遍历两个输入链表,直到两个链表都遍历完毕且没有进位
  3. 计算当前位和:sum = l1.val + l2.val + carry(若链表已结束,对应val为0)
  4. 更新进位:carry = sum // 10
  5. 创建新节点:将sum % 10作为新节点的值添加到结果链表
  6. 移动指针:将三个链表的指针都后移一位

代码实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def addTwoNumbers(l1: ListNode, l2: ListNode) -> ListNode:
    # 创建哑节点作为结果链表的起始点
    dummy = ListNode(0)
    current = dummy
    carry = 0  # 进位初始化为0
    
    # 遍历两个链表,直到都为空且没有进位
    while l1 or l2 or carry:
        # 获取当前节点的值(若链表已结束则为0)
        val1 = l1.val if l1 else 0
        val2 = l2.val if l2 else 0
        
        # 计算当前位的和与进位
        total = val1 + val2 + carry
        carry = total // 10  # 更新进位
        current.next = ListNode(total % 10)  # 创建新节点
        
        # 移动指针
        current = current.next
        if l1:
            l1 = l1.next
        if l2:
            l2 = l2.next
    
    return dummy.next  # 哑节点的下一个节点才是结果的头节点

示例分析

示例 1 详解(对应流程图)

  • 输入链表

    • l1: 2 → 4 → 3(表示数字 342)
    • l2: 5 → 6 → 4(表示数字 465)
  • 相加过程

    1. 个位:2 + 5 = 7 → 进位0 → 结果节点7
    2. 十位:4 + 6 = 10 → 进位1 → 结果节点0
    3. 百位:3 + 4 + 1(进位)= 8 → 进位0 → 结果节点8
    4. 结果链表:7 → 0 → 8(表示数字 807)

示例 3 特殊情况处理

当两个链表长度不同且存在连续进位时:

  • l1: 9→9→9→9→9→9→9(7个9)
  • l2: 9→9→9→9(4个9)
  • 相加后产生连续进位,最终需要在结果链表末尾添加进位1,形成8位结果

复杂度分析

  • 时间复杂度:O(max(m, n)),其中m和n分别是两个链表的长度。需要遍历到较长链表的末尾。
  • 空间复杂度:O(max(m, n)),结果链表的长度最多为max(m, n) + 1(考虑最后一个进位)。

常见错误与注意事项

  1. 忘记处理进位:特别是最后一位相加后仍有进位的情况(如示例3)
  2. 链表长度不同:需要处理一个链表已结束而另一个未结束的情况
  3. 哑节点使用:正确使用哑节点可以简化头节点处理逻辑
  4. 空链表判断:虽然题目说明链表非空,但代码仍需兼容单个节点的情况
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

韩进520

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值