【为进大厂力扣刷题】2. 移除链表元素。顺便讲讲数组与链表

162 阅读2分钟

“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”

一、题目描述:

203. 移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。  

示例 1:

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:

输入:head = [], val = 1
输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[]

提示:

列表中的节点数目在范围 [0, 104] 内
1 <= Node.val <= 50
0 <= val <= 50

二、思路分析:

链表与数组

数组:[1,2,3,4]
链表:1 => 2 => 3 => 4

既然有了数组为什么还需要链表解构,这就要说到两种格式的优缺点:

数组

  • 数组是占用 连续的储存空间,那根据索引去查找元素,就变得很方便,只要知道数组的 储存地址+索引偏移量,例如 arr[3]。那么随机访问的时间复杂度仅为O(1)。
  • 但是增删数据就变得繁琐了,例如 [1,2,3,4,5],想要在2、3中间插一个6,那么3、4、5都要向后移动一个位置。那么他的时间复杂度为O(n)。删除同理,向前移。

链表

  • 链表的储存空间可以不连续,每一个节点有 valnext(指向下一项) 两个属性。通俗的讲像特务,只与自己的下级联系,其他什么都不知道。
  • 链表的查询数据只能从头一项一项来,那么随机访问的时间复杂度为O(n)
  • 增删操作就很简单了,时间复杂度仅为O(1)。(在指定节点的前提下) 例如 1 => 2 => 3,想要在1、2中间添加一项4
插入4
4.next = 1.next
1.next = 4
删除4
1.next = 4.next

回到题目,功能应该是 链表的 循环+删除。那么开干

解法1

var removeElements = function(head, val) {
    // 因为head首项可能也满足条件,那么就加一个守卫指向head。
    let solider = {
        next: head
    }
    let p = solider
    while(p.next){  // 最后一项 next 为 null
        if(p.next.val === val){
            p.next = p.next.next  // 删除操作
        } else {
            p = p.next // 指针后移
        }
    }
    return solider.next
};

image.png 结果不错哈哈哈

解法2

一般循环能写,递归也能实现,那么换个实现方法看看。

递归

  1. 边界条件,找出口不能无限递归
  2. 递进是参数层层传递,每一项按顺序传递进去
  3. 回归是return结果值,每一次都是一次返回。
  4. 逻辑部分,每一层都完整执行。
var removeElements = function(head, val) {
    if(head === null){ // 递归出口
        return null
    }
    head.next = removeElements(head.next, val) // 层层递进
    return head.val === val?head.next:head // 逻辑部分 + 回归return
};

image.png

ok拉,明儿见奥