图示详解删除链表的倒数第K个节点

1、题目描述:

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

给定一个链表:1->2->3->4->5,和 n = 2
当删除了倒数第二个节点后,链表变为 1->2->3->5

说明:给定的n保证是有效的,尝试使用一趟扫描实现。

2、分析如下:
  • 首先想当我们要删除单链表的某个节点的时候,有两种办法:
    A:一个让当前节点的下一个节点的数据域不 断覆盖当前节点的数据域名,然后释放尾节点就好
    B:直接让当前节点的前驱的next域指向当前节点的next域这个是最快捷有效的办法。
  • 删除搞定了,此时我们需要考虑一下倒数第K个节点。
    A :要找到倒数第K个节点一定是要遍历链表的,这里定义slow来标识这个K

在这里插入图片描述
B:这里假设找的是倒数第3个节点,倒数第三个节点是657,这里找的是倒数,可以定义一个变量fast指向尾节点888,从尾节点 倒着走两步就是倒数第三个节点,要找的。
在这里插入图片描述
C:看到这里slow和fast差2步,三个节点能产生的是两个间隔,那就是要找的倒数第K个节点,从尾节点fast走slow就永远差k-1步,这是一个固定的间距。
D:既然这一步能看懂,我们不妨接着大胆的设想,让slow和fast就保持这个间距一起遍历链表,这样当fast走到尾节点的时候,我们的slow就指向的是倒数第K个节点。
F:前面我们知道要找倒数第k个,那fast和slow相差的就是K-1步,三个节点,两个间隔,就是2步嘛,所以我们可以先让fast走k-1步,然后fast和slow一起走,这样当fast走到头,slow就是要删除的喽。

  • 既然要删除的节点已经找到了,这样我们再定义一个prev始终指向slow的前驱就好,然后让prev.next = slow.next即可。
public ListNode removeNthFromEnd(ListNode head, int k) {
        ListNode cur = head;
        int count = 0;
        while(cur != null){
            count++;
            cur = cur.next;
        }
        //当倒数n个节点和链表长度相等时,需要特殊考虑。
        if(count == k){
            return head.next;
        }
        ListNode fast = head;
        ListNode slow = head;
       //fast多走的步数
        while(k-1 > 0){
            if(fast == null){
                return null;
            }
            fast = fast.next;
             k--;
        }
        //两个一起走找到K节点并且删除
        ListNode prev = null;
        while(fast != null && fast.next != null){
             prev = slow;
            fast = fast.next;
            slow = slow.next;
        }
        prev.next = slow.next;
        return head;
    }

注意:

  • 当节点长度count = n的时候,这里包含了一个节点的情况或者多个节点。很容易出现单纯的认为只有一个节点就直接返回null,出现了误区,还有即便是只有一个节点,这样的理解也是不够合理的,因为对于带头节点的链表来讲,当删除head,他的头就是head.next。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值