Floyd判圈法
来源:互联网 发布:mac终端怎么使用 编辑:程序博客网 时间:2024/06/06 00:56
问题:如何检测一个链表是否有环,如果有,那么如何确定环的起点以及环的长度
1. 是否有环
龟兔解法的基本思想可以用我们跑步的例子来解释,如果两个人同时出发,如果赛道有环,那么快的一方总能追上慢的一方。进一步想,追上时快的一方肯定比慢的一方多跑了几圈,即多跑的路的长度是圈的长度的倍数。
基于上面的想法,Floyd用两个指针,一个慢指针(龟)每次前进一步,快指针(兔)指针每次前进两步(两步或多步效果是等价的,只要一个比另一个快就行,从后面的讨论我们可以看出这一点)。如果两者在链表头以外的某一点相遇(即相等)了,那么说明链表有环,否则,如果(快指针)到达了链表的结尾,那么说明没环。
2.环的长度
慢指针与快指针第一次相遇后,继续前进,直到快慢指针相遇,经过的路径就是环的长度。
3. 环的起点
方法:将慢指针(或快指针)移到链表起点,两者同时移动,每次移动一步,那么两者相遇的地方就是环的起点。
原理:设起点到环的起点距离为m,已经确定有环,环的周长为n,(第一次)相遇点距离环的起点的距离是k。那么当两者相遇时,慢指针移动的总距离为i,i = m + a * n + k,因为快指针移动速度为慢指针的两倍,那么快指针的移动距离为2i,2i = m + b * n + k。其中,a和b分别为慢指针和快指针在第一次相遇时转过的圈数。我们让两者相减(快减慢),那么有i = (b - a) * n。即i是圈长度的倍数。利用这个结论我们就可以理解Floyd解法为什么能确定环的起点。将一个指针移到链表起点,另一个指针不变,即距离链表起点为i处,两者同时移动,每次移动一步。当第一个指针前进了m,即到达环起点时,另一个指针距离链表起点为i + m。考虑到i为圈长度的倍数,可以理解为指针从链表起点出发,走到环起点,然后绕环转了几圈,所以第二个指针也必然在环的起点。即两者相遇点就是环的起点。
下面为代码实现:
class Node { private int val; public Node next; public Node(int val) { this.val = val; next = null; } public Node(int val, Node next) { this.val = val; this.next = next; }}public class FloydCircle { //判断链表是否有环 public boolean isCircle(Node head) { if (head == null) return false; Node slow = head; Node fast = head; do { if (fast.next == null || fast.next.next == null) return false; slow = slow.next; fast = fast.next.next; }while (slow != fast); return true; } //求链表环的长度 public int getCircleSize(Node head) { Node slow = head; Node fast = head; do { slow = slow.next; fast = fast.next.next; }while (slow != fast); int step = 0; do { slow = slow.next; fast = fast.next.next; step++; }while (slow != fast); return step; } //求链表环的起始结点 public Node getCircleStartNode(Node head) { Node slow = head; Node fast = head; do { slow = slow.next; fast = fast.next.next; }while (slow != fast); slow = head; while (slow != fast) { slow = slow.next; fast = fast.next; } return slow; }}
0 0
- Floyd判圈法
- floyd判圈法-uva11549
- uva11549 <Floyd判圈法>
- floyd
- Floyd
- Floyd
- floyd
- floyd
- floyd
- Floyd
- FLOYD
- Floyd
- Floyd
- UVa11549 - Calculator Conundrum (Floyd判圈法)
- uva 11549 - Calculator Conundrum (Floyd判圈法)
- UVA 11549 - Calculator Conundrum Floyd判圈法
- Uva 11549 CALCULATOR CONUNDRUM (floyd 判圈法)
- UVa 11549 - Calculator Conundrum(Floyd判圈法)
- 新的思考
- ThoughtWorks笔试题汇总 2016
- nginx 配置 https
- 解决ie6下兼容float 换行问题,解决ie6下padding的时候 宽度不自动扩展问题
- 对于mock的理解
- Floyd判圈法
- C Looooops poj2115 (扩展欧几里得+模线性方程)
- jq/css鼠标经过图片放大效果
- guava 学习笔记 使用瓜娃(guava)的选择和预判断使代码变得简洁
- struts2学习
- spring mvc 异常统一处理方式
- tensorflow数据可视化
- 统计每日单量MySQL语句
- putty的的颜色配置步骤