算法合集 | 链表 | Leetcode 203. 移除链表元素

75 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

前言

本系列文章主要会总结一些常见的算法题目以及算法的易错点,难点,以及一些万用的公式,并且结合实际的 Leetcode 题目来进行加深理解以及实际应用,算法这种东西,属于是一到用时方恨少的类型,在平时总结一些常见的简单算法,经常磨练自己的算法思维,对于日常的开发还是能有不少的帮助的。

  • 今天来介绍一下链表

什么是链表

用一句话来定义链表就是

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成

链表中的每一个节点会包括当前节点的存储数据,以及指向的下一个节点

链表分为 1 单链表 2 双链表 3 单向循环链表 4 双向循环链表

在实际代码中,如何去理解链表

简单的用一张图和一个对象来表示

var node = {
	data: 1,
	next: {
		data: 2,
		next: {
			data: 3
			next: null
		}
	}
}

Pasted image 20221123122621.png

那么在简单的理解了链表的数据结构之后,来看一下 Leetcode 的题目 203. 移除链表元素

Leetcode 203. 移除链表元素

对于现在存在一个链表和一个 val,找到链表中保存的 数据刚好和 val 相等的节点,并且删除节点。

对于链表来说,删除某个链表,相当于让当前结点的上一个结点直接指向下一个结点。

图片.png

上面移除看起来应该是比较简单的,但是要是需要移除的结点是当前链表的第一个结点,那应该要怎么操作呢?

第一种方法,我们可以直接去修改当前的头结点,用 head = head..next 这种方式,直接修改掉当前的头结点为下一个结点,那么这就和上面说的删除中间结点的操作并不相同,那么我们就需要去判断当前需要删除的结点是否为头结点来进行不同的操作。

还有一种方法为虚拟头结点法,我们可以通过在构造一个虚拟的头结点,这个头结点指向当前的头结点,这样当前的头结点就和其他节点一样都为中间结点了,这样就可以采用一样的操作

图片.png

那么对于Leetcode 这道题来说,就也可以通过这两种方法来解决这道题,下面为第二种解法,第一种感兴趣的可以自己去尝试

/**
 * Definition for singly-linked list.
 * 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 removeElements(head: ListNode | null, val: number): ListNode | null {
    const dummyHead = new ListNode(0);
    dummyHead.next = head;
    let node = dummyHead;
    while (node.next !== null) {
        if (node.next.val == val) {
            node.next = node.next.next;
        } else {
            node = node.next;
        }
    }
    return dummyHead.next;
};

图片.png