心路历程:

这道题折磨了我很久,本来想看答案的,最后没有看到,硬是被自己做出来了,就是,有点憋屈,这里面有点经验教训如下:

1、对快指针先走n步后,慢指针再走,之后,到达结尾的时候,慢指针在哪里是有点模糊的,快指针在哪里也是。

这里再强调下,快指针走完了,一点是走到空节点,null里面去的;

慢指针,则是,当快指针,走到结尾时,自动指导了倒数第n个节点。

2、这里现在n步,知道0时,才听停止快指针的脚步,让慢指针跟着走,可以直接用

while(n!=0) { fast = fast.next; n--; } 实现就好了。

3、还有这道题目,有个机关,就是要删除的倒数第n个节点,有可能是头节点,

很容易导致空指针异常的问题,所以,定义了一个临时的头节点填充,并初始化pre = res;

这样当

ListNode res = new ListNode(-1);

res.next = head;

解题思路:

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 官方的写法,增加了我的注释
     * @param head ListNode类
     * @param n int整型
     * @return ListNode类
     */
    public ListNode removeNthFromEnd (ListNode head, int n) {
        // 这里是用一个表头很有意思
        // 当要删除的节点是head头节点时,就可以作为缓冲
        // 所以,下面ListNode pre = res,就是这样巧妙的设计
        ListNode res = new ListNode(-1);
        res.next = head;
        
        // 快指针先走n步
        ListNode fast = head;
        while (n != 0) {
            fast = fast.next;
            n--;
        }
      
        // 快慢指针一起走,到头后慢指针就指到了倒数第n个节点了
        ListNode cur = head;//如果fast为空,就是说明删除的是头节点
        ListNode pre = res; //fast为空,说明是删除头节点,
	                        //之后用pre的next指向下个节点,就删除了头节点了
        while (fast != null) {
            pre = cur;  // 用于指到倒数第n+1个节点
            cur = cur.next; //用于指到倒数第n个节点
            fast = fast.next; //用于走到头
        }
         
        // 删除当前指针
        pre.next = cur.next;
        return res.next;

    }

    /**
     * 我自己的写法,靠自己倒腾出来的
     */
    public ListNode removeNthFromEnd2 (ListNode head, int n) {
        ListNode newHead = new ListNode(0);
        newHead.next = head;

        // 先遍历到第n个节点,
        int i = 0;
        ListNode fast = head;
        while(i < n) {
            fast = fast.next;
            i++;
        }

        // 说明要删除的是头节点
        if(fast == null) {
            ListNode temp = head.next;
            head.next = null;
            head = temp;
            return head;
        }

        // 否则说明删除的非头节点的
        ListNode slow = head;
        ListNode prev = null;
        while(fast!=null) {
            prev = slow;
            slow = slow.next;
            fast = fast.next;
        }

        prev.next = slow.next;

        return head;
    }



}