![]() |
1
4
面试官(似乎)认为以下形状也被认为是有效的,这使问题变得困难:
也就是说,有一个连接,但是列表循环回到连接之前或之后的某个位置。计算列表长度的过程没有直接帮助,因为循环列表的长度没有定义。 首先要注意的是,循环列表末尾的循环长度可以通过这个O(1)内存/O(n)时间过程计算:
例如,考虑循环列表
算法的工作原理如下(t=乌龟,h=兔子):
现在,如果在形成循环连接点的节点之前有x个节点(在示例节点(3)中),即x=2,并且循环由c个节点组成(在示例C=4中),则当乌龟在x步之后首次进入连接点时,兔子在位置(2x-x)%c处的循环中,即(x%c)(在示例中,乌龟enteRS(3)经过2个步骤后,第3个兔子在位置L=(2%4=2),即在节点(5)中(索引为零)。现在,兔子到达乌龟(示例中的1步)将采取(c-l-1)步,因为兔子具有l步的“优势”;这意味着算法的步数直到兔子第一次遇到乌龟为止是
c是已知的(由算法计算),并且可以计算总步数(用s表示),即
假设现在兔子作为q步进的一个额外优势,即兔子在算法开始前向前移动第一个q下一个指针;然后当乌龟进入连接点时兔子在位置((x+q)%c),我们得到
这给出了一个计算从“A”和“B”到公共连接点P的路径长度差异的程序(表示长度A和B及其差异,因此A-B)(假设A>B不失一般性)。 首先从起点A开始运行算法,计算循环长度C并存储步骤数s_a,然后运行它,使乌龟从a开始,然后 野兔在 并计算步骤数s_x。这意味着兔子现在有(a-b)节点的优势,即
因此
即差分给出长度差模c;为了用c计算长度差商,通常从起点b开始运行算法,得到步骤s_b的个数,即所有步骤都在一起。
减去前两个方程得到
方括号中的术语是in]-c,+c[,so
在这个区间内,至多有两个差等于(s-s_x)模c;用它们来找出连接点——问题解决了。 例子:
在计算S_a时,兔子和乌龟在(5)处经过3个步骤相遇,返回循环长度3。在计算S_b时,兔子和乌龟在(6)处经过3个步骤相遇,返回循环长度3。对于S&U,兔子在B进入,乌龟在A进入;他们在(4)的2步后相遇。这给了
也就是说,(a-b)之间的长度差是1个模3;这就给出了可能的长度差-2,+1-2被假设a>b忽略,因此我们得到a=b+1。然后,将第一个+1节点从A向前移动到(2),然后以相同的速度从双臂向前移动,直到找到连接点。 与存在非共享循环和/或没有循环的情况集成,作为读者的练习。 |
![]() |
rookie · 检查函数模板的所有参数包参数是否属于int 1 年前 |
![]() |
ivaigult · -W转换和隐式字符串到布尔类型转换 1 年前 |
![]() |
rainer · 后台插入程序的初始化 1 年前 |
![]() |
Community wiki · 以理智、安全和高效的方式复制文件 1 年前 |
|
Shefali Kanaujia · 对C中向量的向量进行排序++ 1 年前 |
|
Ma Joonyoung · 粗粒度和细粒度链表的时间比较 1 年前 |