给你一个链表,删除链表的倒数第 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]
思路
这题使用双指针法的思路,通俗易懂的说,就是将指针从头节点开始遍历到最后一个节点,然后倒退 n 个节点就是我们需要找的删除节点位置。
转换为双节点的思路就是,双节点同时指向头节点位置,提前移动右节点 n 个节点,再进行同时移动双节点循环,直到右节点为 null
。提前移动右节点实现了之后的倒退 n 个节点操作。
代码
/**
* 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 cur = new ListNode(-1);
cur.next = head;
// 双指针
ListNode left = cur;
ListNode right = cur;
// 右指针提前移动 n 个节点。
// 这样,接下来同时移动双指针时右节点就会比左节点提前 n 个节点
while (n-- > 0) {
right = right.next;
}
// 记录删除节点的前驱节点
ListNode pre = new ListNode();
// 右节点遍历直到链表最后一位
while (right != null) {
// 前驱节点
pre = left;
// 左右指针同时移动
left = left.next;
right = right.next;
}
// 删除节点
pre.next = pre.next.next;
return cur.next;
}
}