题目:
Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
Note: Do not modify the linked list.
Follow up:
Can you solve it without using extra space?
AC:
public class Solution {
public ListNode detectCycle(ListNode head) {
if (null == head || null == head.next) {
return null;
}
ListNode fastNode = head;
ListNode slowNode = head;
int cycleLen = 0;
int pathLen = 0;
int count = 0;
while (null != fastNode && null != fastNode.next) {
fastNode = fastNode.next.next;
slowNode = slowNode.next;
if (fastNode == slowNode) {
break;
}
}
if (fastNode != slowNode) {
return null;
}
fastNode = fastNode.next;
cycleLen = 1;
while (fastNode != slowNode) {
fastNode = fastNode.next;
cycleLen++;
}
slowNode = head;
while (slowNode != fastNode) {
slowNode = slowNode.next;
pathLen++;
}
if (cycleLen > pathLen) {
count = cycleLen - pathLen;
slowNode = head;
}
else {
count = pathLen - cycleLen;
fastNode = head;
}
while (count > 0) {
fastNode = fastNode.next;
count--;
}
while (fastNode != slowNode) {
fastNode = fastNode.next;
slowNode = slowNode.next;
}
return fastNode;
}
}
该题为求链表如果存在圆的情况下,圆的入口节点。
假设该链表存在圆,如图所示:
图中标红的X点为快慢指针的相遇点,但是在该点相遇时,不知道快慢指针是第一次进圆时相遇,还是第n次进圆才相遇。
首先在相遇后,可以再次利用两指针,求出该圆的长度,即b+c。也可以求出从头节点到相遇点的距离,即a+b。这两个长度均为单次的结果,不存在多次绕圆的情况。两者的差值,即为a和c的差值,即为头节点到圆入口与相遇点到圆入口距离的差值,注意有可能a大,也可能c大。距离远者,先前进|a-c|,此时两节点到圆入口距离相同,同时移动,则相遇点即为圆入口。
PS:这题印象很深,当初校招面试某独角兽企业时,写出第141题,判断圆存在与否了,接着让我写出该圆的入口节点。当时天气炎热,加上紧张,头脑很混乱,只模糊的记着大致思路,却一直没写出来,很遗憾。还是自己不够熟练,需要勤加练习。