目录
19. 删除链表的倒数第 N 个结点
方法1 通过链表长度直接删除
方法2 递归加入哨兵节点
ListNode
方法3 快慢指针法
苦难,区区挫折罢了,而我必定站在幸福的塔尖
—— 24.9.22
19. 删除链表的倒数第 N 个结点
给你一个链表,删除链表的倒数第
n个结点,并且返回链表的头结点。示例 1:
输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]示例 2:
输入:head = [1], n = 1 输出:[]示例 3:
输入:head = [1,2], n = 1 输出:[1]提示:
- 链表中结点的数目为
sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
方法1 通过链表长度直接删除
计算链表长度,通过链表长度倒数找到被删除的元素,直接删除该元素
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0, head);
        int num = 0;
        while (head != null) {
            num++;
            head = head.next;
        }
        ListNode cur = dummy;
        for (int i = 0; i < num - n ; i++) {
            cur = cur.next;
        }
        cur.next = cur.next.next;
        ListNode ans = dummy.next;
        return ans;
    }
}
方法2 递归加入哨兵节点
递归加入哨兵节点
因为加入了哨兵节点,所以这里要修改ListNode类的遍历方式,从哨兵节点的下一个节点开始遍历,在ListNode类中加入一个哨兵节点,指向头节点的下一个节点
ListNode
public class ListNode {
    public int val;
    public ListNode next;
    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
    public static ListNode of(int...numbers) {
        ListNode head = new ListNode(0, null);
        ListNode current = head;
        for (int number : numbers) {
            current.next = new ListNode(number, null);
            current = current.next;
        }
        return head;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(64);
        sb.append("[");
        ListNode p = this.next;
        while (p != null) {
            sb.append(p.val);
            if (p.next != null) {
                sb.append(",");
            }
            p = p.next;
        }
        sb.append("]");
        return sb.toString();
    }
}
ppublic class LeetCode203RemoveListData {
    public static ListNode removeElements1(ListNode head, int val) {
        ListNode s = new ListNode(-1,head);
        ListNode p1 = s;
        ListNode p2 = s.next;
        while (p2 != null) {
            if (p2.val == val) {
                p1.next = p2.next;
                p2 = p2.next;
            }else {
                p1 = p2;
                p2 = p2.next;
            }
        }
        return s.next;
    }
    public ListNode removeElements2(ListNode head, int val) {
        if (head == null) {
            return head;
        }
        head.next = removeElements2(head.next, val);
        return head.val == val ? head.next : head;
    }
}

方法3 快慢指针法
定义两个指针,使两个指针中间保持倒数节点+1的位置,是两个指针同时遍历,当快指针遍历到null时,慢指针的位置即是倒数指针的位置
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode s = new ListNode(-1, head);
        ListNode p1 = s;
        ListNode p2 = s;
        // 倒数n位,移动到倒数n+1的位置
        for (int i = 0; i < n + 1; i++) {
            p2 = p2.next;
        }
        while(p2 != null){
            p1 = p1.next;
            p2 = p2.next;
        }
        p1.next = p1.next.next;
        return s.next;
    }
}













![[Meachines] [Medium] Querier XLSM宏+MSSQL NTLM哈希窃取(xp_dirtree)+GPP凭据泄露](https://img-blog.csdnimg.cn/img_convert/030b19e1329fbe507ec7693001dacab7.jpeg)






