LeetCode Notes_#19_删除链表的倒数第N个节点

LeetCode Notes_#19_删除链表的倒数第N个节点

Contents

题目

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.

说明:
给定的 n 保证是有效的。

进阶:
你能尝试使用一趟扫描实现吗?

思路分析

使用双指针法。快指针fast,慢指针slow

算法流程

我们使用双指针,肯定是希望找到待删除节点的前一个节点pre
我们考虑最后的状态,即slow指向prefast指向最后一个节点。
在纸上画出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处改动:

  1. fast先走n+1步
  2. 不需要再fast走完之后进行特殊判断
  3. 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)

posted @ 2020-08-19 17:37  Howfar's  阅读(143)  评论(0编辑  收藏  举报