关闭

如何判断单向链表有环?

2724人阅读 评论(0) 收藏 举报

昨天去面试了一把,面试官给出了这道题。当时我知道一定有什么巧妙的办法,但是我并没有想到。我只是想到了通用的方法,顺序遍历然后为遍历过的节点依次做标志。也试图去想了些特殊的访法,不过都有一定的局限性。事后得知了下面这个较优的方案。
typedef struct NodeTag
{
   struct type data;
   node * next;
}Node;
    题目:如何判断单项链表有死循环?
    答案:定义两个指针p、q,然后让p、q同时从链表头向后查找,注意他们移动的步幅是不同的分别为a
、b,例如p指针每次执行一次【p = p->next;】q每次执行两次【q = q->next;】,如果q先到链尾【if(q->next == NULL)】则没有死循环(这里假设q比p的移动速度要快),如果p、q在此之前相遇了则有死环。

   对于这个答案少不了的还是欣赏,这确实是个good idea.但是返回来一想,会不会有这样的情况,p与q永远不会相遇呢?这里就涉及到a和b应该如何选择的问题,它们的设置必须要保证如果链表上有死环,p、q一定会在有限的步数内相遇。网上有人说a,b的只要是素数就行,有人说a、b大一点好,但a、b的值到底应该如何选择呢?
  
   分析:假设链表上有环的情况,按照前面说的方案经过了多次移动以后p和q都会上环,上环后其实就是一个追逐问题,如果a<b,且a和b距离是h,环长c。设迭代了x次后p和q相遇且相遇时q比p多跑y圈,可得出方程【ax+yc=bx+h】和【b>a】;即【x=(cy-h)/(b-a)】,注意这里的x一定要是正整数。由于c和h都是随机数,所以【(cy-h)】的结果可以是任何一个正整数。问题转变成了a和b必须满足任意整数都可以除尽【(b-a)】,这下好了终于可以得出答案:因为任意整数除以1都等于它本身。这里只要满足条件【b-a=1】 即可。也就是说p和q的步幅只要相差1就可以保证在有限次迭代后可以找出链表上的环。 

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3187次
    • 积分:43
    • 等级:
    • 排名:千里之外
    • 原创:1篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章存档