LeetCode Notes_#19_删除链表的倒数第N个节点
Contents
题目
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
思路分析
使用双指针法。快指针fast
,慢指针slow
。
算法流程
我们使用双指针,肯定是希望找到待删除节点的前一个节点pre
。
我们考虑最后的状态,即slow
指向pre
,fast
指向最后一个节点。
在纸上画出n=2的情况进行分析。
其实这个可以推广到所有的n,都是成立的。
唯一一个特例是:n等于链表长度,那么就相当于让我们删除第一个节点。这种情况下,fast
先走n步之后,变成null
,这时我们返回head.next
即可。
实际上,针对这个特殊情况,我们可以增加一个哑节点,就不需要特殊处理了。
解答1:不使用哑节点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode fast = head;
ListNode slow = head;
//fast先走n步
for(int i = 1;i <= n;i++){
fast = fast.next;
}
//如果走n步后,fast == null,说明删除的是第一个节点
if(fast == null) return head.next;
//然后fast和slow一起走,直到fast指向最后一个节点,此时slow指向删除节点的前一个节点
while(fast.next != null){
slow = slow.next;
fast = fast.next;
}
ListNode pre = slow;
pre.next = pre.next.next;
return head;
}
}
解答2:使用哑节点
使用哑节点的方法,代码有3处改动:
fast
先走n+1步- 不需要再
fast
走完之后进行特殊判断 while
循环中,结束条件是fast
指向null
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode fast = dummy;
ListNode slow = dummy;
//由于是从哑节点开始走,fast先走n + 1步
for(int i = 1;i <= n + 1;i++){
fast = fast.next;
}
//然后fast和slow一起走,直到fast指向null,此时slow指向删除节点的前一个节点
while(fast != null){
slow = slow.next;
fast = fast.next;
}
ListNode pre = slow;
pre.next = pre.next.next;
return dummy.next;
}
}
复杂度分析
两段代码复杂度相同
时间复杂度:O(n)
空间复杂度:O(1)