判断一个链表是否有环
2016-01-22 17:57
387 查看
思路:如果开始有两个指针指向头结点,一个走的快,一个走的慢,如果有环的话,最终经过若干步,快的指针总会超过慢的指针一圈从而相遇。
如何计算环的长度呢?可以第一次相遇时开始计数,第二次相遇时停止计数。
如何判断环的入口点?碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
当fast与slow相遇时,show肯定没有走完链表,而fast已经在还里走了n(n>= 1)圈。假设slow走了s步,那么fast走了2s步。fast的步数还等于s走的加上环里转的n圈,所以
有:2s = s + nr。因此,s = nr。
设整个链表长为L,入口据相遇点X,起点到入口的距离为a。因为slow指针并没有走完一圈,所以:a + x = s,带入第一步的结果,有:a + x =
nr = (n-1)r + r = (n-1)r + L - a;即:a = (n-1)r + L -a -x;
这说明:从头结点到入口的距离,等于转了(n-1)圈以后,相遇点到入口的距离。因此,我们可以在链表头、相遇点各设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。
判断是否有环
计算环的长度
//求环的入口结点
如何计算环的长度呢?可以第一次相遇时开始计数,第二次相遇时停止计数。
如何判断环的入口点?碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
当fast与slow相遇时,show肯定没有走完链表,而fast已经在还里走了n(n>= 1)圈。假设slow走了s步,那么fast走了2s步。fast的步数还等于s走的加上环里转的n圈,所以
有:2s = s + nr。因此,s = nr。
设整个链表长为L,入口据相遇点X,起点到入口的距离为a。因为slow指针并没有走完一圈,所以:a + x = s,带入第一步的结果,有:a + x =
nr = (n-1)r + r = (n-1)r + L - a;即:a = (n-1)r + L -a -x;
这说明:从头结点到入口的距离,等于转了(n-1)圈以后,相遇点到入口的距离。因此,我们可以在链表头、相遇点各设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。
判断是否有环
bool hasCycle(ListNode *head) { ListNode *fast(head), *slow(head); while(fast && fast->next) { fast = fast->next->next; slow = slow->next; if(fast == slow) return true; } return false; }
计算环的长度
int loopLength(ListNode *head) { if(hasCycle(head) == false) return 0; ListNode *fast = head; ListNode *slow = head; int length = 0; bool begin = false; bool again = false; while( fast != NULL && fast->next != NULL) { fast = fast->next->next; slow = slow->next; //超两圈后停止计数,挑出循环 if(fast == slow && again== true) break; //超一圈后开始计数 if(fast == slow && again == false) { begin = true; again= true; } //计数 if(begin == true) ++length; } return length; }
//求环的入口结点
ListNode* findLoopEntrance(ListNode *head) { ListNode *fast = head; ListNode * slow = head; while( fast != NULL && fast->next != NULL) { fast = fast->next->next; slow = slow->next; //如果有环,则fast会超过slow一圈 if(fast == slow) { break; } } if(fast == NULL || fast->next == NULL) return NULL; slow = head; while(slow != fast) { slow = slow->next; fast = fast->next; } return slow; }
相关文章推荐
- debian 搭建svn 服务器
- linux内核启动第二阶段之setup_arch()函数分析-2.6.36
- 18款js和jquery文字特效代码分享
- 不用VS自带的打包工具,不用InstallShield。用C#自己制作安装程序
- 3小时做完3天工作,她是用了什么办法做到的?
- lua中集成第三方拓展c库
- Velocity 用户指南手册中文版(转)
- BPDU Gard / BPDU Filter / Root Guard
- jQuery val() 在不同.NET 环境下显示不同值。
- js选择不同浏览器点击收藏夹功能(主要是 IE与firefox的区别)
- git clone cm source & cm vs android version
- c#读写ini文件
- spring学习概览
- NYOJ 16 矩形嵌套 【DAG模型——嵌套矩形问题】
- 云计算相关资料
- check_mk 客户端安装配置
- 有关Microsoft.Office.Interop.Word的使用例子(未整理)
- 认识nginx配置文件
- Android studio导入eclipse项目混淆打包出错
- adb logcat 查看日志