代码随想录环形链表II

102 阅读2分钟

image.png

分析

  • 链表中有没有环

原理:如果有环便可以一直循环不会出现null节点,那么只需要一个快指针一个慢指针,在前进过程中一定会相遇那么便可以判断是否存在环。假设快指针的移动步长为慢指针的两倍。

  • 如果有环如何找到环大的入口

image.png

将fast指针到环入口距离为x,环入口到fast和slow指针相遇的距离为y,相遇距离到环入口另一半距离为z。 fast与slow相遇时:

fast:x+y+n*(y+z)

slow : y+x

fast = 2*slow

化简即可得到 x= (n-1)(y+z)+z,这里n一定是大于等于1 假设n=1得到 x=z 意味着在fast与slow相遇时,将index1指向head,index2指向相遇的节点,此时相同速度移动两个指针便会在环入口相遇。 即使n>1时,也只是index2在环内多绕几圈最终依旧会在环入口相遇。

疑问

  • 为什么slow在第一次相遇时走的不是多走几圈才会相遇?

因为当slow在入环时开始,两个指针在最多经历len(huan)/(Vfast-Vslow),所以slow不会走满一圈

  • 为什么一开始循环条件可以为 fast.next,fast非空即可不用再加上fast.next.next非空。
fast,slow=head,head
        while fast and fast.next :
            fast=fast.next.next
            slow=slow.next

因为fast.next.next为空不会影响,可以执行这部操作,循环结束即可,但是一旦fast.next为空那便会造成报错,所以加上fast.next.next也没什么影响。

代码

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        fast,slow=head,head
        while fast and fast.next and fast.next.next:
            fast=fast.next.next
            slow=slow.next
            if fast == slow:
                index1=head
                index2=fast
                while index1 != index2:
                    index1=index1.next
                    index2=index2.next
                return index2
        return None

这里非常感谢卡哥b站上视频解析把环形链表讲清楚! 如何判断环形链表?如何找到环形链表的入口? LeetCode:142.环形链表II_哔哩哔哩_bilibili