删除链表的节点

395 阅读2分钟

正题

剑指 Offer 18. 删除链表的节点

给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。

返回删除后的链表的头节点。

注意: 此题对比原题有改动

示例 1:

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

示例 2:

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

解析:

单纯地删除链表中的节点还是比较简单的,具体思路即设置 pre 节点 和 p 节点, pre 节点和 p 节点都是遍历链表所得到的,唯一不同的是,pre 节点要滞后 p 节点一个元素。

为什么要滞后一个元素呢?原因是单向链表是不能回退的,当你找到要删除的节点的时候,需要记录该节点的位置,然后重新遍历,再去用他上一个节点的 next 指针 指向他的下一个节点,用 pre 保存了上一个节点就很方便的可以直接指向 p 的下一个节点达到删除 p 节点的目的了。

代码:

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
 */
var deleteNode = function(head, val) {
    let p = head
    let pre = null
    
    while(p) {
        if (p.val === val) {
            if (!pre) {
                head = p.next
            } else {
                pre.next = p.next
            }
            return head
        }
        pre = pre ? pre.next : p
        p = p.next
    }
};

PS: 有个细节要注意,当要删除的节点是第一个元素时候,我们是没有 pre 指针的,那么只要将 head 指向 head 的 next 就可以了。

使用单指针能否删除节点

答案是可以的,我们只需要以 p 当作是 pre 节点,那么我们要删除的节点为 p.next,我们去判断 p.next.val 是否和 入参 val 相等即可。

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
 */
var deleteNode = function(head, val) {
    let p = head
    if (p.val === val) {
        head = p.next
        return head
    }
    while(p.next.val !== val) {
        p = p.next
    }
    p.next = p.next.next
    return head
};

删除节点的方法还有很多,这里仅仅随意想到2个,记录一下。