给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
示例1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
有没有pos这个条件并不影响做题,判断链表有没有环通常都是采用Floyd算法,即双指针的形式,设立一个快指针和一个慢指针。
假如链表中存在环,那么假设两个同学在操场上跑步,两人同时起跑,一个跑得快一个跑的慢,假设两个同学都一直跑,那么快同学会超过慢同学,并且会在某个点和慢同学相遇。
设定指针的起始位置为head,设定快指针和慢指针的步长(工程上通常设置为1和2),如果有环,那么快指针和慢指针会有重合的时候。
接下来就是明确没有环的时候,当只有一个结点时,快指针的下一个结点为None;快结点的下一个结点的下一个结点为None(步长为2),也说明没有环。
## python3 class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: def hasCycle(self, head: [ListNode]) -> bool: if head == None: return False slow = head fast = head while fast.next != None and fast.next.next != None: slow = slow.next fast = fast.next.next if slow == fast: return True return False
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例1:
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
示例2:
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
示例3:
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
我们先来做一个推导,假设一共有a+b个结点,其中环有b个
f走的步数是s的两倍,则f = 2s
二者相遇的时候f比s多走几个圈,f = s + nb
由上式可得,s = nb , f = 2nb
当二者相遇后,我把s拿到最开始的地方,然后f和s的步长都变为1,如果二者再次相遇会是什么情况?
当s被拿到最开始使,s = 0,f = 2nb
二者相遇只能在圈内,假设s刚好走到圈内,那么s = a,f = a + 2nb
因为2nb是圈数的整数倍,所以刚好在圈的开头(2nb可以去掉),那么此时,s = a,f = a,两人刚好会在开头相遇,然后一起移动。
---------
结论:
用快慢指针能否相遇判断是否有环,如果二者相遇,将慢(快)指针拿到开头,二者以1为步长移动,再次相遇的一定是在环的起始位置。
## python3 class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: def detectCycle(self, head: ListNode) -> ListNode: if head == None return None slow = head fast = head loop = False while fast.next != None and fast.next.next != None: slow = slow.next fast = fast.next.next if slow == fast: loop = True break if loop: slow = head while slow != fast: fast = fast.next slow = slow.next return slow return None