1.题目
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
2.解析
暴力做法不说。这里说说双指针。
指针right是真正遍历完整个链表的指针,而指针left则指向即将删除结点的前一个指针。如下图所示:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
right指针比left指针多便利了2次,也就是参数n
次。
所以首先我们令right指针先遍历n次,考虑可能会删除头结点,所以我们初始化的时候会手动制作一个虚拟头结点dummy,left和right指向dummy。
随后right指针后移n次。
随后right和left一起遍历,直到right到达最后一个结点。
此时left再进行删除操作。
特殊情况
删除head结点
删除尾结点
3.代码
/**
* 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 dummy = new ListNode();
dummy.next = head;
ListNode left = dummy, right = dummy;
// right与left相差n
for (int i = 0; i < n; i++) {
if (right == null) { // 非法n
return dummy.next;
}
right = right.next;
}
// right和left一起遍历
while(right.next != null) {
right = right.next;
left = left.next;
}
// 删除结点
if (left.next != null) {
left.next = left.next.next;
}
return dummy.next;
}
}