2.数据结构与算法——两数相加

117 阅读3分钟

相关技术知识

链表
链表是一种数据结构,它在内存中的存储方式是随机的,多个节点之间并不是连续存放的。例如: 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 开头。

image.png 例:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

使用方法

                递归

复杂度分析

  • 时间复杂度:O(n)\mathcal{O}(n) ,其中 nn 为 l1_1 长度和 l2_2长度的最大值。

  • 空间复杂度:O(n)\mathcal{O}(n)。递归需要 O(n)\mathcal{O}(n)的栈空间。

题目解析

//题目中给定的类
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
        }
    }
}