# 链表

# 数组 vs 链表

  • 数组:增删非首尾元素时往往需要移动元素
  • 链表:增删非首尾元素,不需要移动元素,只需要更改 next 的指向即可

# JS 中的链表

  • JavaScript 中没有链表
  • 可以用Object模拟链表

# 链表的常用操作

  • 遍历
const a = {val: 'a'}
const b = {val: 'b'}
const c = {val: 'c'}
const d = {val: 'd'}
a.next = b 
b.next = c
c.next = d

// 遍历链表
let p = a; // p 是一个指针
while(p) { // 当 p 有值得实惠一直循环
    console.log(p.val)
    p = p.next
}
  • 插入
// 插入
const e = {val: 'e'}

c.next = e
e.next = d
  • 删除
c.next = d

# leetCode: 237. 删除链表中的节点

# 题目描述:

请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点。传入函数的唯一参数为 要被删除的节点 。

现有一个链表 -- head = [4,5,1,9],它可以表示为:

img

示例 1:

输入:head = [4,5,1,9], node = 5 输出:[4,1,9] 解释:给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. 示例 2:

输入:head = [4,5,1,9], node = 1 输出:[4,5,9] 解释:给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.

提示:

链表至少包含两个节点。 链表中所有节点的值都是唯一的。 给定的节点为非末尾节点并且一定是链表中的一个有效节点。 不要从你的函数中返回任何结果。

# 解题思路

  • 无法直接获取被删除节点的上个节点
  • 被删除节点转移到下个节点

# 解题步骤

  • 将被删节点的值改为下个节点的值
  • 删除下个节点
const deleteNode = function(node) {
    node.val = node.next.val
    node.next = node.next.next
}

# leetCode: 206.反转链表

# 题目描述

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

# 解题思路

  • 反转两个节点:将 n+1 的 next 指向 n
  • 反转多个节点:双指针遍历链表,重复上述操作

# 解题步骤

  • 双指针一前一后遍历链表
  • 反转双指针
const reverseList = function(head) {
    let p1 = head
    let p2 = null
    while(p1) {
        // console.log(p1.val, p2 && p2.val)
        const tmp = p1.next
        p1.next = p2
        p2 = p1 
        p1 = temp
    }
    return p2
}

# leetCode: 2. 两数相加

# 题目描述

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

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

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

示例1:

img

输入: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
  • 题目数据保证列表表示的数字不含前导零

# 解题思路

  • 类似小学数学题,模拟相加操作
  • 需要遍历链表

# 解题步骤

  • 新建一个空链表
  • 遍历被相加的两个链表,模拟相加操作,将个位数追加到新链表上,将十位数留到下一位去相加