LeetCode 第2题:两数相加
题目描述
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
难度
中等
题目链接
https://leetcode.cn/problems/add-two-numbers/
示例
示例 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, 100] 内
- 0 <= Node.val <= 9
- 题目数据保证列表表示的数字不含前导零
解题思路
方法:模拟加法运算
这道题本质上是在模拟我们小学学习的加法运算过程,只是在链表中进行。
关键点:
- 链表是逆序存储的,即最低位在链表头部,这正好符合我们从低位到高位的加法运算顺序
- 需要处理进位(carry)情况
- 注意链表长度不同的情况
- 最后还要检查是否有进位需要增加新节点
具体步骤:
- 创建一个虚拟头节点(dummy node),简化插入操作
- 同时遍历两个链表,模拟加法运算:
- 获取当前两个节点的值(如果节点为空则值为0)
- 计算和(需要加上上一步的进位)
- 创建新节点存储个位数
- 更新进位值
- 遍历结束后,检查是否还有进位,如有则添加新节点
- 返回虚拟头节点的下一个节点
时间复杂度:O(max(m,n)),其中 m 和 n 分别为两个链表的长度
空间复杂度:O(max(m,n)),需要创建一个新链表
代码实现
C# 实现
/*** Definition for singly-linked list.* public class ListNode {* public int val;* public ListNode next;* public ListNode(int val=0, ListNode next=null) {* this.val = val;* this.next = next;* }* }*/
public class Solution {public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {// 创建虚拟头节点ListNode dummy = new ListNode(0);ListNode current = dummy;int carry = 0; // 进位值// 当两个链表都没有遍历完,或者还有进位时继续循环while (l1 != null || l2 != null || carry > 0) {// 获取当前节点的值,如果节点为空则值为0int x = l1 != null ? l1.val : 0;int y = l2 != null ? l2.val : 0;// 计算和与进位int sum = x + y + carry;carry = sum / 10;// 创建新节点current.next = new ListNode(sum % 10);current = current.next;// 移动指针l1 = l1?.next;l2 = l2?.next;}return dummy.next;}
}
代码详解
ListNode dummy = new ListNode(0)
:创建虚拟头节点,简化链表操作while (l1 != null || l2 != null || carry > 0)
:- 只要还有节点未处理或者还有进位,就继续循环
int x = l1 != null ? l1.val : 0
:- 如果l1节点存在,获取其值;否则用0代替
sum = x + y + carry
:- 计算当前位的和,包含上一位的进位
carry = sum / 10
:- 计算新的进位值
current.next = new ListNode(sum % 10)
:- 创建新节点,存储个位数
l1 = l1?.next
:- 使用空条件运算符安全地移动指针
执行结果
- 执行用时:92 ms
- 内存消耗:48.4 MB
总结与反思
- 这是一道经典的链表操作题目,考察了:
- 链表的基本操作
- 进位处理
- 边界条件的处理
- 使用虚拟头节点(dummy node)是简化链表操作的常用技巧
- 代码中使用了C#的空条件运算符(?.),使代码更简洁安全
- 关键是要考虑到:
- 两个链表长度可能不同
- 最后可能还有进位需要处理
- 不要忘记释放虚拟头节点
相关题目
- LeetCode 第445题:两数相加 II
- LeetCode 第43题:字符串相乘
- LeetCode 第66题:加一
- LeetCode 第369题:给单链表加一