1、判断有环
一个链表如果没有环,那么一直next,最终会得到null。若有环则一定不会为null。通过这个思想,可以把每次遍历的链表元素保存到一个list中,每次判断是否包含在这个链表中或者是否为空。这无疑是一个可行的办法,但是需要消耗的控件会变大。还有一个经典的办法解决这个问题,那就是快慢指针。
定义两个指针,一个叫fast,一个叫slow。通过这两个指针遍历链表,顾名思义,fast走的快,slow走的慢,如果有环,他们一定会相遇,就是你去追赶某一个人,只要比他快就一定能够追到。当然结束的条件还是为null。我们想象一下,如果在一个环中同一个位置两个指针同时跑,一定会在第二圈结束的时候,也就是起跑的位置相遇。所以上面的问题中,只要相遇的话,慢的指针一定没有超过一圈,快的指针不一定,可能是n圈。
2、判断环的入口
先看一个图
假设在一个带环的链表中,两个指针一起出发,在243点相遇。设出发点到入口点距离为a,入口点到相遇点为x,一个环的全长为c。
看下面式子:
快的指针走了a+x+nc,慢的指针走了a + x,还有一个条件,a+x+nc = 2(a + x),可以导出:a = (n-1)c + (c-x)。从起始点的位置到入口点的位置的长度等于n-1圈再加上从相遇点到入口点的距离。现在,如果我让两个速度相等的指针一个从起始点出发,一个从相遇点出发,等到从起始点出发的指针走到入口点的时候,从相遇点出发的指针走了n-1圈和c-x,恰好也是入口点,这样,我们就能得到入口点了。
3、求环的长度
知道了入口点,求长度就太简单了,遍历一遍就好了。