橙子何橙

V1

2022/11/10阅读:13主题:萌绿

学算法刷LeetCode:19. 删除链表的倒数第 N 个结点

Problem: 19. 删除链表的倒数第 N 个结点

思路1

计算链表长度。

因为删除的是倒数的第 N 个结点,只要把正数的节点位置算出来,删除节点即可。

解题方法1

步骤1:计算正数的位置、 链表只能从头节点开始遍历,要找到正数节点的位置,我们只需要: 链表的长度 - 倒数节点的位置 + 1

这里需要注意,我们要找的位置是删除节点的前一个位置,而不是要删除节点的位置。

步骤2: 删除节点 将要删除的节点的前驱指向它的下下一个节点。

image.png
image.png

注意:这里我们使用了添加哑节点(dummy node)的技巧, 它的 next 指针指向链表的头节点,这时候就不需要对头节点进行特殊的判断了。

复杂度1

  • 时间复杂度:

, L 为链表长度

  • 空间复杂度:

Code1

/**
 * 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} n
 * @return {ListNode}
 */

var getLength = function(head{
    let n = 0;
    while(head) {
        n++;
        head = head.next;
    }
    return n;
}
var removeNthFromEnd = function(head, n{
    const length = getLength(head);
    const preIndex = length - n + 1;
    const dummy = new ListNode(0);
    dummy.next = head;
    let cur = dummy;
    for(let i = 1; i < preIndex; i++) {
        cur = cur.next;
    } 
    cur.next = cur.next.next;
    return dummy.next;
};

思路2

双指针 使用两个指针,first 和 second,first 指针让它先走 N 步,然后两个指针一起走,first 指针走到链表结束位置,此时 second 指针恰好就是在要删除的节点。当我们希望得到要删除节点的前驱节点,可以在初始时将 second 节点指向哑节点。

image.png
image.png

复杂度2

  • 时间复杂度:

, L 为链表长度

  • 空间复杂度:

Code2


/**
 * 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} n
 * @return {ListNode}
 */

var removeNthFromEnd = function(head, n{
    const dummy = new ListNode(0);
    dummy.next = head;
    let first = head, second = dummy;
    for (let i = 0; i < n; ++i) {
        first = first.next;
    }

    while(first) {
        first = first.next;
        second = second.next;
    }

    second.next = second.next.next;
    
    return dummy.next;
};

参考: 删除链表的倒数第N个节点

分类:

前端

标签:

数据结构与算法

作者介绍

橙子何橙
V1

前端工程师