19.删除链表的倒数第N个节点
思路1(两次遍历):
- 为了避免头结点删除的情况,本题使用虚拟头结点
- 第一次遍历获得链表长度
- 第二次遍历到 要删除的元素的 前一个节点,并使 node1.next = node1.next.next;,最后返回 虚拟头结点的next 即可
代码实现:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
int count = 0;
ListNode node = head;
ListNode dummy = new ListNode(-1,head);
ListNode node1 = dummy;
while (node != null) {
count++;
node = node.next;
}
for (int i = 1; i <= count - n; i++) {
node1 = node1.next;
}
node1.next = node1.next.next;
return dummy.next;
}
}
思路2(一次遍历 快慢指针):
![在这里插入图片描述](https://img-blog.csdnimg.cn/75bd8ea981614e9db7c854bcdf09f612.png)
- 由图可知,当快指针指向null,慢指针和它间隔N个节点时,此时的慢指针使需要删除的节点的前一个节点
- 由此可知,当快指针走了 (N+1) 之后,慢指针才开始走
- 最后slow.next = slow.next.next;即可
- 注意本题可能头节点head会被删除,所以设虚拟头结点。这样做可以避免讨论头结点被删除的情况,不管原来的head有没有被删除,直接返回dummy.next即可
代码实现:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyHead = new ListNode(-1, head);
ListNode slow = dummyHead;
ListNode fast = dummyHead;
while (n-- >= 0) {
fast = fast.next;
}
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummyHead.next;
}
}