问题引入:
一位室友去京东面试,面是回来后给我说他在一个题目上跪了,我向他询问是什么题目;他告诉我:”如何判断一个链表中存在环?“。
问题分析:
我听到题目后,稍微想了一下,得到了一个比较中规中矩的方法。
方法一:
设置一个从链表头开始遍历,每遍历一个节点,首先判断其是否被标记。如果没有被标记,则标记该节点;若果遍历到已经被标记的节点,则说明该链表中存在环。时间复杂度O(n),空间复杂度O(n)。
显然上述方法不会是面试官想要的结果。之后便徐问了一下度娘。由此得出了方法二。
方法二:
首先创建两个指针1和指针2,同时指向这个链表的头节点。然后开始一个大循环,在循环体中,让指针1每次向下移动一个节点,让指针2每次向下移动两个节点,然后比较两个指针指向的节点是否相同。如果相同,则判断出链表有环,如果不同,则继续下一次循环。时间复杂度O(n),空间复杂度O(1)
例如链表A->B->C->D->B->C->D,两个指针最初都指向节点A,进入第一轮循环,指针1移动到了节点B,指针2移动到了C。第二轮循环,指针1移动到了节点C,指针2移动到了节点B。第三轮循环,指针1移动到了节点D,指针2移动到了节点D,此时两指针指向同一节点,判断出链表有环。
看到这里,我不免觉得是个好方法。但是我同时有了疑惑,为什么两个指针一个步长为 1 ,一个步长为 2 ?如果一个步长为 1 ,一个步长为 3 是否可以呢?如果一个步长为 2 ,一个步长为 3 呢?
无限思索中。。。。。。。。。。
我们考虑按照方法二的思想去解决链表中是否存在环的问题。为此,设一链表中存在一个度为s( s >=3)的环,这里的度指的是该环上含有的节点个数。
设指针一的步长为m,指针二的步长为n。假设他两个指针在进入链表环中所处的节点分别为p,q(0<=p,q<s)。如果存在一个自然数K,使得( p + m*k )% s = ( q + n*k ) % s。则说明这两个指针的步长值适用于用方法二去求解链表中是否存在度为s的环。
如果m,n存在某种关系使得总是存在一个自然数K,使( p + m*k )% s = ( q + n*k ) % s成立。m,n就符合题意。方法二给出的m,n的值就是 1 和 2 。
( p + m*k )% s = ( q + n*k ) % s
==》 ( q + n*k )- ( p + m*k ) % s ==0
==》 ((q-p)+ (n-m)* k )可以被 s 整除。
s 是一个大于等于3 的自然数,(-s<p-q<s)若使得总存在一个K使得上式成立。则有(n-m)==1
突然的想法,不确定是否正确。望大神批评指正。