[路飞]_leetcode_19.删除链表的倒数第 N 个结点

137 阅读1分钟

思考

题目给出:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

那么就是要删除节点。删除节点的操作只需要将前一个节点的指向指到待删除节点后一个节点就行了。

所以我们只需要找到待删除节点的前一个节点就行了。

解题思路

两种办法:

第一种:

  1. 先遍历链表,获取链表长度s;
  2. 根据给定的n值,找到需要将指针走s-n步;
  3. 找到待删除节点的前一个位置,删除节点。

第二种(进阶,只遍历一遍链表):

  1. 首先将指向第一个节点的cur指针先走n步;
  2. 然后cur指针继续走,期间指向虚拟头节点hair的pre指针随着cur移动而移,这样他们的距离时刻保持着 n 步;
  3. 等cur指针指向null时停止移动;
  4. 此时pre指针的下一个是待删除的节点。

Tips: 虚拟头节点是因为有可能删除的节点为头节点,为了方便管理链表而创建的。因为没有虚拟头节点时,删除或新增头节点的操作与其他节点的操作不一样,为了保持节点操作的统一性。

n = 2
pre    cur
hair -> 1 -> 2 -> 3 -> 4 -> 5 -> null

pre              cur
hair -> 1 -> 2 -> 3 -> 4 -> 5 -> null

       pre            cur
hair -> 1 -> 2 -> 3 -> 4 -> 5 -> null

            pre            cur
hair -> 1 -> 2 -> 3 -> 4 -> 5 -> null

                 pre            cur
hair -> 1 -> 2 -> 3 -> 4 -> 5 -> null

                 pre            cur
hair -> 1 -> 2 -> 3      -> 5 -> null

代码

var removeNthFromEnd = function(head, n) {
    if (!head) return head;
    let hair = new ListNode(-1, head), pre = hair, cur = head;
    while(n--) {
        cur = cur.next;
    }
    while(cur) {
        pre = pre.next;
        cur = cur.next;
    }
    pre.next = pre.next.next;

    return hair.next;
};