华为面试题:怎么判断链表中是否有环?????

laji2003 2005-11-26 08:33:19
华为面试题:怎么判断链表中是否有环?????
该链表不一定是循环单链表或双链表。
...全文
3596 49 打赏 收藏 转发到动态 举报
写回复
用AI写文章
49 条回复
切换为时间正序
请发表友善的回复…
发表回复
gogowhy 2006-01-12
  • 打赏
  • 举报
回复
m
luvybird 2006-01-04
  • 打赏
  • 举报
回复
mark
JerKii 2005-11-29
  • 打赏
  • 举报
回复
The solution from <<Expert C Programming>> ...

First, eliminate the pathological case of a 3-element list with a cycle from element 2 to 1. Keep two pointers. One at element 1 and the next at element 3. See if they are equal; if not, move P1 by one and P2 by two. Check and continue. If P1 or P2 is null, there is no loop. If there is one, it will definitely be detected. One pointer will eventually catch up with the other (i.e., have the same value), though it might take several traversals of the cycle to do it.

当每次移动P2指针两次时,就可以得到最佳答案。但不知道作者当初是怎么想到需要使用移动两次的方法呢?这里有什么理论依据吗?
nipcdll 2005-11-29
  • 打赏
  • 举报
回复
studying。。。。
csucdl 2005-11-29
  • 打赏
  • 举报
回复
说说看啊
runall 2005-11-29
  • 打赏
  • 举报
回复
我觉得应该用拓扑算法来解决
csucdl 2005-11-29
  • 打赏
  • 举报
回复
楼上的也行啊
alphakiller 2005-11-29
  • 打赏
  • 举报
回复
呵呵,c专家编程上就有,有四种方法
pt2519515 2005-11-29
  • 打赏
  • 举报
回复
佩服csucdl(csucdl) 的算法

下面算法易想到,但效率不如csucdl(csucdl) 的算法

bool CircleInList(Link* pHead)
{
if(pHead == NULL)return false;
Link *pTemp;
Link *pTemp2 ;
int i,j;
for(i=0,pTemp = pHead;pTemp;i++, pTemp=pTemp->next)
{
for(j=0,pTemp2 = pHead;j<i;j++,pTemp2 = pTemp2 ->next)
{
if(pTemp2 == pTemp)return true;
}
}
return false;
}
chtfyy 2005-11-29
  • 打赏
  • 举报
回复
mark
poweryitian 2005-11-29
  • 打赏
  • 举报
回复
mark
amitabha 2005-11-29
  • 打赏
  • 举报
回复
mark
toumao 2005-11-29
  • 打赏
  • 举报
回复
cdo(一个坏人)
本身就很长的链也可以判断的,
用(系统内存+虚拟内存)/sizeof(结构体),
可以知道最多有多少个结点,
然后我统计循环次数。
呵呵。
ahjoe 2005-11-28
  • 打赏
  • 举报
回复
两个指针追是个好办法。
laoren_80 2005-11-28
  • 打赏
  • 举报
回复
ding
cangxuan 2005-11-28
  • 打赏
  • 举报
回复
佩服 csucdl(csucdl)
creative55 2005-11-28
  • 打赏
  • 举报
回复
if(n==null&flag==1) {return 0} 改成
if(n==null||flag==1) {return 0}
如果是尾结点或是有停止标志就停止所有的访问。
creative55 2005-11-28
  • 打赏
  • 举报
回复
做天回去想了一下,觉得可以做出来就是效率比较低,
为每个接点增加一个唯一id
int a[max_note],
int flag=0;
int insert(int i,int num)
{
int j=0;
for(j=0;j<i;j++)
{
if(a[j]==num) return 0; //在前i个数中存在这个数
}
a[i]=num;
return 1;
}
visit(note* n,int i)
{
if(n==null&flag==1) {return 0}
else if(!insert(i,n->id))
{
flag=1;
return 0 //这条链路上出现过这个接点,表明有环,退出所有的访问 }
}
else
{
i++;
visit(note->left,i);
visit(note->right,i);
//visit(note->other,i);
}
}



visit(head,0); //从根接点开始,链路的第一个接点开始。
JerKii 2005-11-28
  • 打赏
  • 举报
回复
我想最简单的算法就是每次从该链表中的一个节点开始遍历,如果最终能够回到该节点,则存在环,不过这样的算法复杂度为O(n^2)

使用两个指针进行跟进遍历的话,当存在环时,可通过这两个指针的“位置关系”来判断是否存在环,这样的复杂度为O(n),但是似乎存在以下问题,怎样判断这两个指针的先后顺序被改变了呢?如果换的跨度为1,那很好办,采用p1 == p2->next就可以了,但是如果环的跨度大于1呢?该怎么判断,总不能采用p1 >= p2->next吧!
cdo 2005-11-28
  • 打赏
  • 举报
回复
to toumao(偷猫):

萬一鏈表本身就很長那怎麼辦:)
加载更多回复(29)

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧