算法之移除链表元素

99 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

关于算法系列已更新部分文章,后续会陆续增加内容:

【1】 算法之用动态规划实现斐波那契数列

【2】 算法之双指针法的应用

【3】 算法之链表的含义

题目描述

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

示例 1:

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

输出:[1,2,3,4,5]

示例 2:

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

输出:[]

注:在 leetcode 中不需要单独定义节点和链表,在注释中可以看到提供了定义部分的实现方式,所以只负责功能点的实现即可。

关于链表

在前面介绍过关于链表的一些基本理念,一个链表是由0到多个结点连接而成的,每个节点都有自己的结构,包括数据域和指针域。

移除链表元素是链表的基本操作之一,除此之外还有插入修改、查找、删除等基于链表的常规操作。

如下图所示,删除元素实际上是一个断开连接,重新连接的过程:

被删除节点的前一个节点的next,不再存储被删除节点的地址,而是被删除节点的下一个节点的地址

image.png

代码实现

关键点:

  • 设置一个虚拟的头节点,这样当删除的是头节点的时候就不需要额外进行操作
  • 删除时需要遍历整个链表,通过循环定位到被删除的元素。初始位置是虚拟头节点
  • 因为删除操作需要改变上一个元素的next,所以判断的条件是cur.next.val === val,即当前节点的下一个节点的值和要删除的值相等
  • 当找到目标元素cur时,将其 next 的指向改变(cur.next = cur.next.next),continue 进入下一次循环(可能还有待删除的节点)
  • 当还未找到时,继续移动指针(cur = cur.next)
  • 循环结束,返回新的头节点
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
 */
var removeElements = function(head, val) {
    const ret = new ListNode(0, head);
    let cur = ret;
    while(cur.next) {
        if(cur.next.val === val) {
            cur.next =  cur.next.next;
            continue;
        }
        cur = cur.next;
    }
    return ret.next;
};