思路

双指针,快指针先走n次,保持快慢指针直接的间距是n
然后快慢指针同时后移,快指针为null时,满指针后一个就是要删除的节点。

关键点

哨兵节点,减少特殊节点的判断

代码

Node

逻辑

package leetcode.linked;

import leetcode.ListNode;

/**
 * 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
 * <p>
 * 给定一个链表: 1->2->3->4->5, 和 n = 2.
 * <p>
 * 当删除了倒数第二个节点后,链表变为 1->2->3->5.
 */
public class N19 {

    /**
     * 使用哨兵节点的原因在于减少边界条件的判断,如12345 取倒数第5个
     * 如果没有哨兵节点,倒数第五个就是首节点,需要额外判断
     * @param head
     * @param n
     * @return
     */
    public ListNode removeNthFromEnd(ListNode head, int n){
        if  (head == null) {
            return head;
        }
        if (head.next == null && n == 1) {
            return null;
        }
        ListNode tempHead = new ListNode(-1);
        tempHead.next = head;

        ListNode fast = tempHead;
        ListNode slow = tempHead;

        while (n > 0 && fast != null) {
            fast = fast.next;
            n--;
        }

        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }

        slow.next = slow.next.next;
        return tempHead.next;

    }


    public static void main(String[] args) {
        int[] ints = new int[]{1, 2, 3, 4, 5};
//        int[] ints = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//        int[] ints = new int[]{1};
        ListNode listNode = ListNode.makeNode(ints);
        ListNode.print(listNode);

        N19 n19 = new N19();
        ListNode listNode1 = n19.removeNthFromEnd(listNode, 5);
        ListNode.print(listNode1);
    }
}

结果

1,2,3,4,5,
2,3,4,5,

哒哒队长
7 声望4 粉丝