打印

判断链表是否有环

[复制链接]
1883|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
韩山童|  楼主 | 2016-12-27 10:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
给定一个单链表,只给出头指针head:
1、如何判断是否存在环?
2、如何知道环的长度?
3、如何找出环的连接点在哪里?
4、带环链表的长度是多少?

解法:
1、对于问题1,使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。
2、对于问题2,记录下问题1的碰撞点p,slow、fast从该点开始,再次碰撞所走过的操作数就是环的长度s。
3、问题3:有定理:碰撞点p到连接点的距离等于头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。(证明在后面附注)
4、问题3中已经求出连接点距离头指针的长度,加上问题2中求出的环的长度,二者之和就是带环单链表的长度


2.代码:
/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:

     //寻找连接点
    ListNode *detectCycle(ListNode *head) {
        ListNode *p1=head;
        ListNode *p2 = head;
        while (p2 && p2->next) {

        p1 = p1->next;
        p2 = p2->next->next;
        if (p1 == p2)break;
        }
        if (p2==NULL || p2->next == NULL)
            return NULL;
       p1 = head;
       while (p1 != p2){
           p1 = p1->next;
           p2 = p2->next;
       }
       return p1;
    }

//判断是否有环
bool isExistLoop(ListNode* head) {
         
       ListNode *p1=head;
        ListNode *p2 = head;
        while (p2 && p2->next) {

        p1 = p1->next;
        p2 = p2->next->next;
        if (p1 == p2)break;
        }
         return  !(p2==NULL || p2->next == NULL);
}


};


附注
问题2的证明如下:
链表形状类似数字 6 。
假设甩尾(在环外)长度为 a(结点个数),环内长度为 b 。
则总长度(也是总结点数)为 a+b 。
从头开始,0 base 编号。
将第 i 步访问的结点用 S(i) 表示。i = 0, 1 ...
当 i<a 时,S(i)=i ;
当 i≥a 时,S(i)=a+(i-a)%b 。
分析追赶过程:
两个指针分别前进,假定经过 x 步后,碰撞。则有:S(x)=S(2x)
由环的周期性有:2x=tb+x 。得到 x=tb 。
另,碰撞时,必须在环内,不可能在甩尾段,有 x>=a 。
连接点为从起点走 a 步,即 S(a)。
S(a) = S(tb+a) = S(x+a)。
得到结论:从碰撞点 x 前进 a 步即为连接点。
根据假设易知 S(a-1) 在甩尾段,S(a) 在环上,而 S(x+a) 必然在环上。所以可以发生碰撞。
而,同为前进 a 步,同为连接点,所以必然发生碰撞。
综上,从 x 点和从起点同步前进,第一个碰撞点就是连接点。




相关帖子

沙发
Meyeah| | 2016-12-27 11:26 | 只看该作者
本帖最后由 Meyeah 于 2016-12-27 11:34 编辑

有毛意义啊?

使用特权

评论回复
板凳
michael_llh| | 2016-12-27 11:44 | 只看该作者

面试就是要问,但是具体的应用就不是特别清楚了

使用特权

评论回复
地板
Meyeah| | 2016-12-27 11:52 | 只看该作者
michael_llh 发表于 2016-12-27 11:44
面试就是要问,但是具体的应用就不是特别清楚了

好吧!谢谢版主科普

使用特权

评论回复
5
angus118| | 2016-12-27 11:55 | 只看该作者
学C学到链表,就不学了。   

使用特权

评论回复
6
韩山童|  楼主 | 2016-12-27 11:55 | 只看该作者

玩过操作系统就知道了啊

使用特权

评论回复
7
火山LF| | 2016-12-27 11:56 | 只看该作者
不明觉厉,听说童子的C很厉害,要多多请教您呀~~~

老师当年说链表不考,然后就没看了。。。。

使用特权

评论回复
8
michael_llh| | 2016-12-27 11:57 | 只看该作者
火山LF 发表于 2016-12-27 11:56
不明觉厉,听说童子的C很厉害,要多多请教您呀~~~

老师当年说链表不考,然后就没看了。。。。

还是很重要的!有时间可以多研究看看。

使用特权

评论回复
9
michael_llh| | 2016-12-27 11:58 | 只看该作者
Meyeah 发表于 2016-12-27 11:52
好吧!谢谢版主科普

之前面试题有看到过。所以。 。多扩展一些知识面总是好的

使用特权

评论回复
10
michael_llh| | 2016-12-27 11:58 | 只看该作者
韩山童 发表于 2016-12-27 11:55
玩过操作系统就知道了啊

能大概解释一下操作系统当中那个地方需要用有环的链表进行实现吗

使用特权

评论回复
11
韩山童|  楼主 | 2016-12-27 12:00 | 只看该作者
火山LF 发表于 2016-12-27 11:56
不明觉厉,听说童子的C很厉害,要多多请教您呀~~~

老师当年说链表不考,然后就没看了。。。。

不要相信哥,哥只是个传说...

使用特权

评论回复
12
韩山童|  楼主 | 2016-12-27 12:03 | 只看该作者
angus118 发表于 2016-12-27 11:55
学C学到链表,就不学了。   

链表本质上是高级的数据类型啊

使用特权

评论回复
13
韩山童|  楼主 | 2016-12-27 12:06 | 只看该作者
michael_llh 发表于 2016-12-27 11:58
能大概解释一下操作系统当中那个地方需要用有环的链表进行实现吗

其实也是用来检测的,不然遇到有环的链表,而你却不知道,这样程序就在某个地方死循环了啊,谁能保证写出来的链表没有环呢?或者你的链表被某个程序修改了,出现了环,如果下一个程序使用的时候不检测是否有环,那也会导致死循环啊。

使用特权

评论回复
14
michael_llh| | 2016-12-27 12:07 | 只看该作者
韩山童 发表于 2016-12-27 12:06
其实也是用来检测的,不然遇到有环的链表,而你却不知道,这样程序就在某个地方死循环了啊,谁能保证写出 ...

恩,好的!

使用特权

评论回复
15
angus118| | 2016-12-27 12:10 | 只看该作者
韩山童 发表于 2016-12-27 12:03
链表本质上是高级的数据类型啊

大学教材数据结构有一章节不就是讲的链表。

使用特权

评论回复
16
火山LF| | 2016-12-27 13:31 | 只看该作者
michael_llh 发表于 2016-12-27 11:57
还是很重要的!有时间可以多研究看看。

版主,建议你换个头像,然后我们就可以记住你啦~~~

使用特权

评论回复
17
michael_llh| | 2016-12-27 13:58 | 只看该作者
火山LF 发表于 2016-12-27 13:31
版主,建议你换个头像,然后我们就可以记住你啦~~~

好嘞。

使用特权

评论回复
18
皈依| | 2016-12-27 14:55 | 只看该作者
学到了~
感谢分享~

使用特权

评论回复
19
王紫豪| | 2016-12-27 16:51 | 只看该作者
意义非常大,这个东西,就好比盖房子的大梁,没有大梁也能迁就着盖房子,但是有几个大梁,房子坚固无比。

使用特权

评论回复
20
Meyeah| | 2016-12-27 18:45 | 只看该作者
yyy71cj 发表于 2016-12-27 17:41
任何技术的出现,都不要急于怀疑它的意义,说不定某日就用上了…… ...

大白兔说的对

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

43

帖子

1

粉丝