返回中间节点;返回倒数k节点;判断是否为环形链表(返回入环第一个节点)

Posted 小写丶H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了返回中间节点;返回倒数k节点;判断是否为环形链表(返回入环第一个节点)相关的知识,希望对你有一定的参考价值。

今天我们使用典型的快慢指针解决这几个典型问题

一.返回中间节点

问题

给定一个头结点为 head 的非空单链表,返回链表的中间结点。(如果有两个中间结点,则返回第二个中间节点)

思路

这里我们设置两个指针,slow和fast,一个走一步,一个走两步,等fast走完链表,那么slow就在中间节点。
这里比较简单也好想,我就不画图了。一些小细节,我也在代码里解释到了。

代码

public ListNode middleNode(ListNode head) {
        //定义快慢指针
        ListNode fast=head;
        ListNode slow=head;
        //快指针遍历完的的标志
        //这里fast!=null和fast.next!=null,这两个不能换位置哦,防止空指针异常。
        //当fast为null时,就不会判断fast.next了。
        while(fast!=null&&fast.next!=null){
            //走两步
            fast=fast.next.next;
            //走一步
            slow=slow.next;
        }
        return slow;
    }

二.返回倒数k节点

问题

输入一个链表,输出该链表中倒数第k个结点。
(问题简洁,我们也好考虑)

思路

首先依然是两个指针,slow和fast,求倒数第k个,那么我们就让fast先走(k-1)步;因为返回的是slow,为什么是k-1步,也很好理解,不太理解的可以这样想。如果是求倒数第一个节点,那么slow和fast便应该处于同一个节点上。画图遍历一遍就可以理解了。

代码

public ListNode FindKthToTail(ListNode head,int k) {
        //为空直接结束
        if(head==null){
             return null;
         }
        //求得倒数k不合法那也不行,k大的不合法在下面处理
        if(k<=0){
            return null;    
        }
        //定义快慢指针
        ListNode fast=head;
        ListNode slow=head;
        //让fast先走k-1步
        while((k-1)!=0){
            //这里就是在处理如果k大于链表的长度,那么依然返回null
            if(fast.next!=null){
                fast=fast.next;
                k--;
            }else{
                return null;
            }
        }
        //让slow和fast同时一块走动,当fast到尾部时,结束循环
        while(fast.next!=null){
            fast=fast.next;
            slow=slow.next;
        }
        //返回slow
        return slow;
    }

三.判断是否有环形链表

问题

给定一个链表,判断链表中是否有环。
(如果链表中存在环,则返回 true 。 否则,返回 false 。)

环一定是存在尾部。

思路

定义一个快慢指针,slow和fast。slow走一步,fast走两步,当存在环的时候,slow和fast因为存在差距,所以在环中一定相遇。当slow==fast,那么就证明存在环;当fast.next ==null,那么证明没有环

代码

public boolean hasCycle(ListNode head) {
        //定义快慢指针
        ListNode fast=head;
        ListNode slow=head;
        //fast走两步,slow走一步
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            //相遇证明存在环
            if(fast==slow){
                break;
            }
        }
        //证明没有环
        if(fast==null || fast.next==null){
            return false;
        }
        return true;
    }

如果要返回其环的第一个节点

问题

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

思路

定义快慢指针,slow和fast,slow走一步,fast走两步,先找到slow和fast在环中的相遇位置;之后重置slow=head,然后继续走,但是这时,slow走一步,fast也走一步,当slow和fast相遇的时候,那么就是环入口的第一个节点。

代码

 public ListNode detectCycle(ListNode head) {
        //定义快慢指针
        ListNode fast=head;
        ListNode slow=head;
        //fast走两步,slow走一步
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            //相遇存在环
            if(fast==slow){
                break;
            }
        }
        //确保存在环
        if( fast == null || fast.next==null){
            return null;
        }
        //让slow退回到head
        slow=head;
        //这时让slow和fast同时走一步,这个需要理解上面我画的图。
        while(slow!=fast){
            slow=slow.next;
            fast=fast.next;
        }
        return slow;
    }

以上是关于返回中间节点;返回倒数k节点;判断是否为环形链表(返回入环第一个节点)的主要内容,如果未能解决你的问题,请参考以下文章

链表经典面试题(反转链表,中间节点,倒数第k个节点,合并分割链表,删除重复节点)

看了有助于你面试的单链表的OJ面试题

链表题 剑指21.删除链表的倒数第n个节点剑指22.链表的倒数第k个节点234.回文链表141.环形链表142.环形链表Ⅱ 160.相交链表 21.合并两个有序链表

leetcode链表

每日一练(剑指offer)链表中倒数最后k个节点

数据结构之链表OJ练习检验你的链表水平是否合格