题目:给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
提示:
- 每个链表中的节点数在范围 [1, 100] 内
- 0 <= Node.val <= 9
- 题目数据保证列表表示的数字不含前导零
要将两个逆序存储的链表表示的非负整数相加,我们可以模拟手算加法的过程。
算法步骤:
-
初始化:创建一个虚拟头节点 dummyHead,用于简化结果链表的构建。同时,初始化一个指针 res 指向 dummyHead,用于构建结果链表。还需要一个变量 carry 来存储进位。
-
逐位相加:遍历两个链表,对每一位进行相加,同时加上上一次迭代的进位 carry。更新 carry 为新的进位。
-
处理进位:如果遍历完两个链表后仍有进位,需要继续创建新的节点直到进位为0。
-
返回结果:返回 dummyHead.next,即结果链表的头节点。
复杂度分析:
-
时间复杂度:O (max(m, n)),其中 m 和 n 分别是两个链表的长度。我们最多遍历两个链表的长度。
-
空间复杂度:O (max(m, n)),因为需要创建新的节点来存储结果。在最坏的情况下,如果两个链表长度相等,且每一位相加都产生进位,需要创建与链表长度相同的新节点。
我的 Java 代码:
/*** Definition for singly-linked list.* public 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 res = dummyHead;int carry = 0; // 存储进位值// 逐位相加while(l1 != null || l2 != null){int val1 = (l1==null)? 0:l1.val;int val2 = (l2==null)? 0:l2.val;int sum = val1+val2+carry; // 当前位的和加上进位carry = sum/10; // 更新进位值res.next = new ListNode(sum % 10); // 创建新节点,存储当前位的结果// 移动链表指针res = res.next;if(l1 != null) l1 = l1.next;if(l2 != null) l2 = l2.next;}// 如果最后还有进位,要添加一个新的节点if(carry>0){res.next = new ListNode(carry);}return dummyHead.next;}
}