追赶法检测链表环点的算法正确性分析
2012-07-05 22:54
197 查看
C专家编程在附录A2讨论了链表环检测的算法,实现一下,算法一通过设置标志,复杂度O(N),算法二就是所谓的追赶法,算法还是很好理解的,在链表尾部形成的环中,假设两个步伐不一致的的人在绕圈,总有一个交点,但是要证明该算法的正确性似乎还要费一些精力。
先给出实现:
[code]ExpertCProgramming,ChineseEdition
[/code]
设链表长度为n,出现环点处为a.
要证明在有环链表中,步长为1和2的两个向量移动必有相遇点,也就意味着要解方程。
向量1移动k步之后所在的点应该是:
向量2移动k步之后所在的点应该是:
其中的除法运算应视作求模运算。
显然解方程就是求存在这样的k使得两个向量组有共解。比如如果k=0,则k=2k,意味着在链表第一个节点就开始循环。
如果循环点就是链表尾端,则意味着n=a,于是(2k-a)mod(n-a+1)永远为0,=>a=k,意味着a步之后就能侦测出现环。
如果是其它情况,就意味着要解方程:
k=(2k-a)mod(n-a+1)+a(1)
先给出实现:
/*
[code]ExpertCProgramming,ChineseEdition
Howtodetectloopinlinkedlist,p274,solution1
*/
intcheck_loop1(pnodelist)
{
pnodep=list;
while(p!=NULL)
{
if(p->flag==1)
{
return1;
}
else
{
p->flag=1;
}
p=p->next;
}
return0;
}
/*
ExpertCProgramming,ChineseEdition
Howtodetectloopinlinkedlist,p274,solution4
*/
intcheck_loop2(pnodelist)
{
pnodep1=list;
pnodep2=list;
if(p1==p2->next)
{
return1;
}
while(p1->next!=NULL&&p2->next!=NULL)
{
p1=p1->next;
p2=p2->next->next;
if(p1==p2)
{
printf("%d",p1->value);
return1;
}
}
return0;
}
[/code]
设链表长度为n,出现环点处为a.
要证明在有环链表中,步长为1和2的两个向量移动必有相遇点,也就意味着要解方程。
向量1移动k步之后所在的点应该是:
向量2移动k步之后所在的点应该是:
其中的除法运算应视作求模运算。
显然解方程就是求存在这样的k使得两个向量组有共解。比如如果k=0,则k=2k,意味着在链表第一个节点就开始循环。
如果循环点就是链表尾端,则意味着n=a,于是(2k-a)mod(n-a+1)永远为0,=>a=k,意味着a步之后就能侦测出现环。
如果是其它情况,就意味着要解方程:
k=(2k-a)mod(n-a+1)+a(1)
或者另外一个
(k-a)mod(n-a+1)+a=(2k-a)mod(n-a+1)+a
,(2)
要证明对于任意的n与a,都有整数k存在使得等式成立。
---------------------------------------------
现观察方程(2),等式两边消去a后这是一个典型的同余方程,我们根据同余的定义(这里我参考了Rosen的《离散数学及其应用》中文版p152),要使方程成立,则有且仅有(n-a+1)|(2k-a-k+a),即n-a+1整除k,于是我们知道k的值就是d*(n-a+1),其中d为正整数,且k>=a(这是很明显的,否则步长为1的向量还没走到环点,也意味还没进环呢
),于是我们知道方程(2)必然有解。分析完毕。
再注:第一个向量组中的两个表达式其实都可以用(k-a)mod(n-a+1)+a表示。
复杂度分析:
已知k的形式如:k=d*(n-a+1)且k>=a,故两向量第一次相遇时的步长k就取第一个大于a的d*(n-a+1),其步长是线性的,故复杂度可以表示为O(N).
还能再精确一点嘛?能否确定第一个k不小于链表长度呢?因为对比我简单的草稿,所有的结果都暗示可能有这个结论。
如果是死理性派在这里,他们肯定会说这是应该的,假设他们就在这里,现猜测:第一个k应该<=n,为证明猜想,现需要求解不等式n>=d*(n-a+1)>=a即:n+1>d*(n-a+1)>a-1
即:(n+1)/(n-a+1)>d>(a-1)/(n-a+1)
于是需要证明存在这样的正整数d。而域『(a-1)/(n-a+1),(n+1)/(n-a+1)』的长度为(n-a+2)/(n-a+1)显然长度大于1,
于是可知必然存在满足不等式的正整数d。于是
我们就此得知,在n步之内,必然两向量相遇。也意味着步长为1的向量顶多走n步,而别忘了,n是单链表的长度(节点数)。
于是找到环所需要的时间复杂度就是O(N),也即是O(1).
------------------------------------------------------------
相关文章推荐
- 确定链表环的长度与入口,以及算法的正确性分析
- SURF算法应用工业检测之二(算法原理分析)
- 「算法精解_C语言描述」链表_循环链表的实现与分析
- 基于规则评分的密码强度检测算法分析及实现(JavaScript)
- 深度学习目标检测算法性能分析
- 异常点检测算法分析与选择
- 基于规则评分的密码强度检测算法分析及实现(JavaScript)
- AdaBoost中利用Haar特征进行人脸识别算法分析与总结2——级联分类器与检测过程 .
- 【数据结构和算法分析】单链表的基本实现
- 边界检测算法分析与实现
- 记(java数据结构与算法之顺序表与链表深入分析)
- C/C++面试之算法系列--怎样快速检测出一个巨大的单链表中是否具备死链及其位置
- OSEA中QRS波检测算法代码分析-未完待续
- 密码强度检测算法分析及实现(JavaScript)案例说明
- 算法与数据结构基础系列(一): 链表的常见问题分析及实现
- 【3D算法】相交碰撞检测分析
- 算法 - 检测是否链表存在环
- paip.检测信用卡账单数据的正确性算法
- OSEA中QRS波检测算法代码分析-未完待续
- 链表环检测算法