判断链表是否有环,求环的入口点及环长

今天的内容主要包括三部分,RT。

1。判断链表是否带环

判断链表是否带环,我们可以采用在头结点设两个指针,一个叫fast,一个叫slow,fast一下走两步,而slow一下走一步。如果链表中存在环的话,那么fast和slow必定会在环中相遇。若链表中没有环的话,那么fast必定现于slow指针先到达链表的尾节点(->next = Null)。我们现在来思考一个问题,为什么链表中存在环,则slow和fast会在环中相遇?这个道理,我们可以联想我们跑步追赶的例子,跑道是前面一段直行路,

后面是一个圆圈,当跑步选手进入环形跑道之后就只能在环形跑道里面继续奔跑。有两名选手在起点同时出发,那么我们很容易明白跑得快的选手肯定会追赶上跑的慢的选手。哎,生活中都是学问啊,有木有???

2. 求环的入口点

老实说,求环的入口点有点复杂。我也是在看了一些前辈们的文章才比较清楚到底是怎么一回事(http://www.cnblogs.com/youxin/p/3303172.html)。我们先看一幅图,这幅图也是我在程序中构造带环链表的原型。


如上图所示,12为带环链表的入口点,简单分析可知243是fast和slow的相遇点(鹊桥相会啊==!),a为环入口点到头结点的路程,x为相遇点到环入口点的路程。我们假设slow指针走过的路程为s,那么fast指针走过的路程则为2s,假设环长为c。且有

2s = s + nc

s = a + x

有上述式子,我们可以得到

a + x = nc

a = nc – x

a = (n – 1)c + c -x

式子化来化去,到这儿,我们是不是感觉有点不对经,好想如果在头结点位置和相遇点位置分别再派出两名跑步选手,并且他们都每次只跑一步,好像会在环的入口点相遇啊!!!恭喜你,答对啦!具体原因我们再分析分析最后一个式子就能明白了。啊。。。。求个环的入口点,我容易嘛我??

3.求环长

求环长就比较容易啦,没用到什么数学知识,对于数学知识捉急的我真是终于松了一口气。就是再环的入口点设一指针和一计数器,让这一指针在环里面跑,计数器不断自增。当这一指针回到环的入口点的时候,环长就出来啦!

4.完整代码请见:

http://www.anycodex.com/blog/?p=97

5.测试平台www.anycodex.com


明天的任务是求两链表是否相交,在链表存在有环的情况。继续努力,机会只留给有准备的人!!!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
判断一个链表是否有环可以使用快慢指针的方法,具体实现如下: ```c #include <stdio.h> #include <stdlib.h> struct ListNode { int val; struct ListNode *next; }; // 判断链表是否有环 bool hasCycle(struct ListNode *head) { if (head == NULL || head->next == NULL) { return false; // 链表为空或只有一个节点,必然无 } struct ListNode *slow = head; struct ListNode *fast = head->next; while (slow != fast) { if (fast == NULL || fast->next == NULL) { return false; // 快指针到达链表末尾,无 } slow = slow->next; fast = fast->next->next; } return true; // 快慢指针相遇,有环 } int main() { // 创建链表 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 3(形成一个) struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode)); head->val = 1; head->next = (struct ListNode *)malloc(sizeof(struct ListNode)); head->next->val = 2; head->next->next = (struct ListNode *)malloc(sizeof(struct ListNode)); head->next->next->val = 3; head->next->next->next = (struct ListNode *)malloc(sizeof(struct ListNode)); head->next->next->next->val = 4; head->next->next->next->next = (struct ListNode *)malloc(sizeof(struct ListNode)); head->next->next->next->next->val = 5; head->next->next->next->next->next = (struct ListNode *)malloc(sizeof(struct ListNode)); head->next->next->next->next->next->val = 6; head->next->next->next->next->next->next = head->next->next; // 入口是节点 3 // 判断链表是否有环 bool has_cycle = hasCycle(head); if (has_cycle) { printf("链表有环\n"); } else { printf("链表\n"); } return 0; } ``` 输出结果为: ``` 链表有环 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值