NC3 链表中环的入口结点

描述

给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。

数据范围: 面试练习题(二)_指针移动面试练习题(二)_链表_02

要求:空间复杂度 面试练习题(二)_链表_03,时间复杂度 面试练习题(二)_指针移动_04

输入描述:

输入分为2段,第一段是入环前的链表部分,第二段是链表环的部分,后台会根据第二段是否为空将这两段组装成一个无环或者有环单链表

返回值描述:

返回链表的环的入口结点即可,我们后台程序会打印这个结点对应的结点值;若没有,则返回对应编程语言的空结点即可。

示例1

输入:

{1,2},{3,4,5}

返回值:

3

说明:

返回环形链表入口结点,我们后台程序会打印该环形链表入口结点对应的结点值,即3


代码解析:

  • step 1:使用BM6.判断链表中是否有环中的方法判断链表是否有环,并找到相遇的节点。
  • step 2:慢指针继续在相遇节点,快指针回到链表头,两个指针同步逐个元素逐个元素开始遍历链表。
  • step 3:再次相遇的地方就是环的入口。
public class Solution {
    //判断有没有环,返回相遇的地方
    public ListNode hasCycle(ListNode head) {
        //先判断链表为空的情况
        if (head == null)
            return null;
        //快慢双指针
        ListNode fast = head;
        ListNode slow = head;
        //如果没环快指针会先到链表尾
        while (fast != null && fast.next != null) {
            //快指针移动两步
            fast = fast.next.next;
            //慢指针移动一步
            slow = slow.next;
            //相遇则有环,返回相遇的位置
            if (fast == slow)
                return slow;
        }
        //到末尾说明没有环,返回null
        return null;
    }

    public ListNode EntryNodeOfLoop(ListNode pHead) {
        ListNode slow = hasCycle(pHead);
        //没有环
        if (slow == null)
            return null;
        //快指针回到表头
        ListNode fast = pHead;
        //再次相遇即是环入口
        while (fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}


class Solution:
    #判断有没有环,返回相遇的地方
    def detectCycle(self, pHead: ListNode):
        slow = self.hasCycle(pHead)
        #没有环
        if slow == None: 
            return None
        #快指针回到表头
        fast = pHead 
        #再次相遇即是环入口
        while fast != slow: 
            fast = fast.next
            slow = slow.next
        return slow
    
    def hasCycle(self , head):
        #先判断链表为空的情况
        if head == None: 
            return None
        #快慢双指针
        fast = head 
        slow = head
        #如果没环快指针会先到链表尾
        while fast != None and fast.next != None: 
            #快指针移动两步
            fast = fast.next.next 
            #慢指针移动一步
            slow = slow.next 
            #相遇则有环
            if fast == slow: 
                #返回相遇的地方
                return slow 
        #到末尾则没有环
        return None