本系列文章为《剑指Offer》刷题笔记。
刷题平台:牛客网
快慢指针
基于以下两个结论:
(1) 设置快慢指针,假如有环,他们最后一定相遇。
(2) 两个指针分别从链表头和相遇点继续出发,每次走一步,最后一定相遇与环入口。
证明结论1:设置快慢指针fast和low,fast每次走两步,low每次走一步。假如有环,两者一定会相遇(因为low一旦进环,可看作fast在后面追赶low的过程,每次两者都接近一步,最后一定能追上)。
证明结论2:
设:
链表头到环入口长度为 - - a
环入口到相遇点长度为 - - b
相遇点到环入口长度为 - - c
如下图所示:
则:相遇时
快指针路程=a+(b+c)k+b ,k>=1 其中b+c为环的长度,k为绕环的圈数(k>=1,即最少一圈,不能是0圈,不然和慢指针走的一样长,矛盾)。
慢指针路程 = a+b
快指针走的路程是慢指针的两倍,所以:(a+b) * 2=a+(b+c)k+b
化简可得:
a=(k-1)(b+c)+c
这个式子的意思是: 链表头到环入口的距离=相遇点到环入口的距离+(k-1)圈环长度。
其中k>=1,所以k-1>=0圈。
所以两个指针分别从链表头和相遇点出发,最后一定相遇于环入口。
时间复杂度为O(n),空间复杂度为O(1)
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
if not pHead:
return None
pFast,pSlow = pHead,pHead
while pFast:
# pFast走的快,它先去探还有没有路
if pFast.next:
pFast = pFast.next.next
else:
return None
pSlow = pSlow.next
if pFast == pSlow: # 此时pSlow停在遇见点
break
newHead = pHead
while newHead != pSlow: # pslow和newHead分别从遇见点和pHead出发,一步一步走,必然能够找到入口
newHead = newHead.next
pSlow = pSlow.next
return pSlow
https://blog.csdn.net/CSDN_SUSAN/article/details/103041082?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.not_use_machine_learn_pai&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.not_use_machine_learn_pai
https://blog.csdn.net/qq_36643449/article/details/106240794