分析
- 链表中有没有环
原理:如果有环便可以一直循环不会出现null节点,那么只需要一个快指针一个慢指针,在前进过程中一定会相遇那么便可以判断是否存在环。假设快指针的移动步长为慢指针的两倍。
- 如果有环如何找到环大的入口
将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