算法_删除链表倒数第n个节点(#19)

80 阅读2分钟

题目

给个链表,删除链表倒数第n个节点,并返回链表的头节点

image.png

分析一波

删除的那个节点的前一个节点指向删除节点后一个节点就行。

要找到待删除节点的前一个节点,如果n是倒数第n个节点,那么待删除节点的前一个节点就是length-n, 因为待删除节点是length-n+1。

待删除节点的next=  待删除节点的next.next。

链表a->b->c, 要删除节点b, 那么a节点指向c节点就行。

删除正数第n个节点就是n, 删除倒数第n个节点就是length-n+1就ok。

解题方法

方法一

比较简单但是稍微麻烦。  

先从头开始走一遍,拿到链表的length,然后再走length-n个节点,让这个节点的下一个节点指向它的下下一个节点。

方法二

设置一个哨兵节点q指向head的上一个节点,
然后p指向头节点head,让 p走了n(倒数删除的节点数)步之后,
再让q节点和p节点一块走(代码中这里:在这之前要先判断一下p下一个节点是否为null也就是判断它是否把链表走完了),
当p的下一个节点为null时,也就是链表走完了,
这时q指向的当前节点就是倒数的删除节点的前一个节点,
那么只让这个节点的下一个节点指向它下下一个节点就可以啦。

其实这种方式就还是利用length-n来找到倒数删除节点的上一个节点。

实践,上代码

 
var removeNthFromEnd = function(head, n) {
    if(!head) return head;
    let list=new ListNode(-1,head),q=list,p=head;
    while(n--) p=p.next;
     //这种是只有一个节点的情况下,然后删除一个节点,最终就是个空的。
    if(!p) return head.next;
    while(p){
    q=q.next;
    p=p.next;
    }
    q.next=q.next.next;
    return head;
};

利用p,q去遍历节点,从而得到被删除节点的前一个节点
本质就是:length-n=删除节点前一个节点,p先走了n个节点,然后再让q从头走,p也继续走,p走完,q正好走到被删除节点的前一个节点

正数第n个节点=链表数-倒数第n个节点+1;
那么被删除的第n个节点的前一个节点=链表数-倒数第n个节点;
只要让被删除的那个节点的前一个节点指向删除节点后一个节点就ok啦;
--n当前结果直接就减掉1,n--当前结果还是原值,但是它两的n当场就减掉1;