题目描述
解题思路
图中紫色节点为相遇节点,若快慢指针相遇,必定满足如下关系:
-
我们使用两个指针,它们起始都位于链表的头部。随后慢指针每次向后移动一个位置,而快指针向后移动两个位置。如果链表中存在环,则快 指针最终将再次与 慢指针在环中相遇。
-
当慢指针进入环以后,慢指针还没走完一个环的时候,快指针必定与之相遇,此时快指针可能已经走了n次环了。因此走过的距离为:s=a+n*(b+c)+b
-
任意时刻,快指针走过的距离都是慢指针的两倍 所以 2*(a+b)=a+n*(b+c)+b 所以得出 a=nb+nc-b 即是 a=(n-1)b+nc 即是 a=c+(n-1)(b+c)
-
从3可知,慢指针走完a表示着快指针走完c加n-1圈周长,因此他们会在入口节点相遇。
解题代码如下
/**
* @description:
* @author: lilang
* @version:
* @modified By:1170370113@qq.com
*/
public class ListSolution {
public ListNode detectCycle(ListNode head) {
if (head == null) {
return null;
}
ListNode goFast, goSlow;
goFast = goSlow = head;
boolean isCycle = false;
while (goFast != null && goSlow != null) {
goFast = goFast.next;
if (goFast == null) {
break;
} else {
goFast = goFast.next;
}
goSlow = goSlow.next;
if (goFast == goSlow) {
isCycle = true;
break;
}
}
if (!isCycle) {
return null;
}
goSlow = head;
while (goFast != goSlow) {
goFast = goFast.next;
goSlow = goSlow.next;
}
return goSlow;
}
public static void main(String[] args) {
System.out.println(null == null);
}
}
解题方法二
直接记录节点是否访问过,如果访问过表示存在环,否则不存在。
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode pos = head;
Set<ListNode> visited = new HashSet<ListNode>();
while (pos != null) {
if (visited.contains(pos)) {
return pos;
} else {
visited.add(pos);
}
pos = pos.next;
}
return null;
}
}
来源:oschina
链接:https://my.oschina.net/jiansin/blog/4838375