如何判断链表是否有环
使用hash
遍历链表,将元素放入map或set中,发生碰撞即有环,碰撞的位置即环入口位置。
使用快慢指针
快指针(一次走两步),慢指针(一次走一步),若快指针可走到环末尾,则链表无环;若快指针追上慢指针,则有环。
快慢指针速度差为一次走一步,且快指针速度为慢指针的两倍,所以若有环,则快指针一定会与慢指针相遇。
如何判断环入口的位置
设链表起点为点A,环入口位置为点B,快慢指针相交位置为点C,A与B的距离为x,B与C的距离为y,C与B的距离为z(距离按照指针走的方向的路程计算)。因为快指针速度为慢指针的两倍(快指针一定可以在 慢指针在环内走一圈内 追上慢指针),所以:
(快指针走一圈环遇到进入环内的慢指针):
快指针的路程为A->B->C->B->C,慢指针的路程为A->B->C,x+y+z+y=2(x+y),可得z=x,即从链表头开始到环入口位置与快慢指针相遇位置到环入口位置相等。
(快指针走多圈环遇到进入环内的慢指针):
快指针的路程为A->B->C->B->C->B->......->C,慢指针的路程为A->B->C->B->......->C,x+y+(z+y)*n=2(x+y),n*z+(n-1)y=x,(n-1)(y+z)+z=x,(n-1)len+z=x[len为环的长度],即从链表头开始到环入口位置 与 快慢指针相遇位置到环入口位置+(n-1)个环的长度(在环入口位置再走n-1个环的长度仍在环入口的位置)相等。
令一指针从头结点出发,一指针从快慢指针相遇位置出发,相遇处即为环入口位置。