目录
简介:
本篇文章将解释如何去判断链链是否带环即原理
以及寻找入环点。
什么是带环链表?
如上图所示,在一个单链表的基础上,在链表的后一部分形成了一个循环链表,也就是说一个单链表的尾节点的next没有指向NULL而是指向了一个循环链表。
如何判断是否为带环链表:
快慢指针(快2慢1):
如果我们使用快慢指针,那么快指针在入环的时候慢指针也到了前面不带环链表的一半的位置,如下图所示。
那么当慢指针入环时,快指针又走了一段距离。
是带环链表:此时假设fast与slow的距离为s,因为快指针每次都会比慢指针快一步,因此如果是一个代换链表的话快指针一定会在环内追上慢指针。只需判断slow==fast即可证明这是一个带环链表。
非带环链表:如果当如果快指针fast走到了NULL,即把这个链表走完了,那么他就是一个不带环的链表,判断fast==NULL即可。
快慢指针(快?慢1):
在上面我们知道了快指针1次走2步慢指针1次走1步的情况可以判断,那如果说当快指针一次走2,3,4.....的情况下也可以使快慢指针相遇吗,他们有没有可能一直错过不会相遇呢?
接下来我们就来进行讨论;
快指针为3:
假设当快指针为3的时,slow进环时fast与它的距离为N那么距离变化如下图:
根据分析上看似乎真的会有永远追不上的情况 ,然而永远追不上也是有条件的,条件有两个:
1:N是及奇数
2:S-1也是奇数(S是偶数)
也就是说,要同时存在S是偶数,N是奇数才能永远追不上。那么有没有可能这追不上的条件不存在呢?因此我们还需要做进一步的分析才能得到准确的答案。
因此我们需要找一些等式看看是不是不会存在N是奇数的同时S是偶数。
我们假设前面不带环的长度为L来找等式:
因此追不上的条件是不存在的!!!
当fast的值为4,5,6......时推导是一样的,因此我们就可以得出大结论
结论:
一定追得上!!!
如何找到入环点?
思路一:
我们将fast与slow相遇点称为meet。
结论:
为让meet节点和链表的头节点head同时走,当meet和head相遇时就正好是入环节点。
思路二:
我们将fast和slow相遇点称为meet。
我们先进行两步操作:
1:新建newhead=meet->next
2: 让meet->next=NULL
这样我们的链表变成了如图所示:
也就等于
这样问题就变成了寻找两个相交链表的相交节点的问题求解即可。