19 删除链表的倒数第N个节点
public ListNode removeNthFromEnd(ListNode head, int n) {
这道题 真的史诗级滑铁卢
本以为遇到以前的嫁接题
结果差点被空指针异常坑死
总是报错的是 [1] 1
只有一个节点的 删除倒数第一个
题目所带的测试用例没有[1] 2
如果使用这个测试用例 方法一会报错 方法二不会
方法一
- 建立哨兵节点 next指向head
- 建立快慢指针 均与哨兵相等
- 令快指针先走n+1步
- 然后快慢指针一起走
- 快指针指空的时候
- 慢指针指向倒数第n+1个(即 下一个为要删除的节点) 因为返回倒数第n个是令快指针先走n步 这里不要搞混
- 令slow的next指向slow的next的next(即 跳过slow的next)
- 返回哨兵的next
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode sentinel = new ListNode(0);
sentinel.next = head;
ListNode fast = sentinel;
ListNode slow = sentinel;
for(int i = 0; i <= n; i++){// 注意这里的等于
fast = fast.next;}
while(fast != null) {
fast = fast.next;
slow = slow.next;
}
slow.next=slow.next.next;
return sentinel.next;
}
方法二(注释划线部分仍正常运行)
- 建立count
- 建立快慢指针 与头节点相等
如果head的next为空 // 空链表head为null返回head
如果head的next的next为空 // 只有一个节点的链表如果删除倒数第2个的节点返回head的next
如果删除倒数第1个的节点令head的next指向空返回head
- 假如 fast的next不为空
- count++
- fast后移
- 如果count<=n
- continue
- 如果count>n
- slow后移一个
- 如果count<n // 这句才是防止空指针的关键
- 返回head的next
- slow的next指向slow的next的next
- 返回头节点
public ListNode removeNthFromEnd2(ListNode head, int n) {
int count = 0;
ListNode fast = head;
ListNode slow = head;
while(fast.next != null) {
count++;
fast = fast.next;
if (count <= n) continue;
else slow = slow.next;
}
if (count < n) return head.next;
slow.next = slow.next.next;
return head;
}