相关技术知识
链表
链表是一种数据结构,它在内存中的存储方式是随机的,多个节点之间并不是连续存放的。例如: 3001 、 4937、3812...
多个节点由于是随机存储的,所以无法像数组那样,只要下标➕1,就可以得到下一个节点了。所以链表在每个节点保存了下一个节点的指针,通过指针可以获取下一个节点,如果没有下一个节点,则指针指向 空值(null)。
递归
函数调用自身。例如:
function recursion(){
recursion()
}
recursion()
不过这样调用下去,没有尽头。所以递归一定要有一个条件,可以终止递归。
function recursion(num:number){
if(num > 5){
return
}
recursion(++num)
}
recursion(1)
可选链 ?.
访问 null 或 undefined 的属性时,不会报错。
// Cannot read properties of null (reading 'name')
null.name
//undefined
null?.name
题目介绍
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
例:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
使用方法
递归
复杂度分析
-
时间复杂度: ,其中 为 l 长度和 l长度的最大值。
-
空间复杂度:。递归需要 的栈空间。
题目解析
//题目中给定的类
class ListNode {
val: number;
next: ListNode | null;
constructor(val?: number, next?: ListNode | null) {
this.val = val === undefined ? 0 : val;
this.next = next === undefined ? null : next;
}
}
//题目中给定的函数声明
function addTwoNumbers(
l1: ListNode | null,
l2: ListNode | null,
//添加一个 carry 形参,用于表示进位
//如:5 + 8 = 13,则 carry 传 1
carry = 0
): ListNode | null {
// 递归边界:l1 和 l2 都是空节点
if (l1 === null && l2 === null) {
// 如果有进位,则额外创建一个节点
//如:500 + 500 = 1000,则 千位的节点是就新创建的
return carry ? new ListNode(carry) : null;
}
//如果 l1 为 null,则l2一定有数据,交换两个的数据,使l1有值
if (l1 === null) {
[l1, l2] = [l2, l1];
}
//此时 l1 一定有数据,但做TS判断,避免下面报TS错误
if (l1) {
// 节点值和进位加在一起
carry += l1.val + (l2?.val ?? 0);
// 下面用l1作为新数据的载体
//取相加后的个位数
l1.val = carry % 10;
//传入下一个节点的数据,并递归
l1.next = addTwoNumbers(
l1.next,
l2 ? l2.next : null,
// 获取进位值
Math.floor(carry / 10)
);
}
//返回相加后的链表
return l1;
}
// l1 = [2,4,3],
const f1 = new ListNode(3);
const f2 = new ListNode(4, f1);
const l1 = new ListNode(2, f2);
//l2 = [5,6,4]
const s1 = new ListNode(4);
const s2 = new ListNode(6, s1);
const l2 = new ListNode(5, s2);
const result = addTwoNumbers(l1, l2)
//result
{
"val": 7,
"next": {
"val": 0,
"next": {
"val": 8,
"next": null
}
}
}