解题思路
思路一
在遍历时用一个哈希表记录当前已经遍历的结点,当出现某个结点已经存在于表中时,这就是环的入口
class Solution:
def EntryNodeOfLoop(self, pHead):
node = pHead
traset = set()
while node and node not in traset:
traset.add(node)
node = node.next
return node
思路二
快慢指针,很数学了。
设置两个快慢指针。快指针每次走两步,慢指针每次走一步,快指针和慢指针一定会在环中相遇。因为慢指针进环后,每一次快慢指针的运动,都可看成是快指针在追赶慢指针一步,快慢指针的环中初始位置差异一定小于环的长度。那么一定会在慢指针走回环头(即一圈)之前追上。
class Solution:
def EntryNodeOfLoop(self, pHead):
fast, slow = pHead, pHead
while fast and fast.next: #不对slow判断是因为fast和fast.next的路径已经涵盖了slow
fast = fast.next.next
slow = slow.next
if fast == slow:
slow = pHead
while slow != fast:
slow = slow.next
fast = fast.next
return slow
return None
思路二的更自然的思考方式
链表中一般我们要找某个特定的位置,都会使用快慢指针。
该题若想让快慢指针最终汇于环形入口点。则应该让快指针先走长度L(或kL),慢指针从起点开始走。这样当慢指针走到a,快指针刚好走到a+L(或a+(k+1)L)。两者必定相遇于入口。于是现在的问题就转化为,如何让快指针先走kL?
我们可以先设置一轮快慢指针,快指针每次走两格,慢指针每次走一格。最终快慢指针必定相遇于环内某点b。此时有2(a+b)=a+b+kL
,=>a+b=kL
,我们发现相遇点刚好满足条件,此时快指针实际已走2kL
。那么把慢指针移到起点,快慢同时走即可。