19. 删除链表的倒数第 N 个结点 JavaScript实现

277 阅读2分钟

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

题目链接

一、栈

1、设置一个哑节点,避免删除头节点的问题。构成新的链表 2、遍历新的链表,然后将节点压入栈中。 3、从栈顶弹出n个元素。那么再从栈顶弹出元素的时候,就是被删除节点的前一个节点pre。 4、根据pre节点删除倒数第n个元素。

二、需要注意的事项

1、要删除节点 y,我们需要知道节点 y 的前驱节点 x,并将 x 的指针指向 y 的后继节点。但由于头节点不存在前驱节点,因此我们需要在删除头节点时进行特殊判断。但如果我们添加了哑节点,那么头节点的前驱节点就是哑节点本身,此时我们就只需要考虑通用的情况即可。 2、对于被删除节点的空间释放问题,需要考虑。 设置哑节点之后,需要把遍历的指针放着这个上面,才能避免删除头节点的问题

三、代码实现

/**
 * 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) {
    // 设置一个哑节点
    let dummyNode = new ListNode(-1);
    dummyNode.next = head;
    let cur = dummyNode; // 使用cur指针从哑节点开始遍历链表

    // 定义一个栈,用来存放链表中的节点
    let stack = [];

    // 遍历整个链表,将节点放到栈中
    while(cur){
        stack.push(cur);
        cur = cur.next;
    }

    // 从栈顶弹出n个元素,
    for(let i=0;i<n;i++){
        stack.pop();  
    }
    
    // 此时再弹出一个元素就是被删除节点的前一个节点
    let prev = stack.pop();  
    prev.next = prev.next.next; // 删除倒数第n个元素
    
    return dummyNode.next;
};

四、双指针实现

var removeNthFromEnd = function(head, n) {
    let dummyHead = new ListNode(-1,head)
    let pre = head, count = 0

    // 得到链表的长度
    while(pre){
        count++
        pre = pre.next
    }
    let cur = dummyHead

    // 指针前行到需要删除的节点的前一个节点
    for(let i=0;i<=count-n-1;i++){
        cur = cur.next
    }
    cur.next = cur.next.next

    return dummyHead.next
};