您的位置:首页 > 其它

LeetCode Linked List Cycle II

2015-12-17 10:41 295 查看
题目:

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.
题意:
给定一个单链表,首先判断是否存在环,如果有环,那么就输出环开始的那个节点,如果没有环,那么就直接输出null。

题解:

此题和之前的判断单链表是否存在环类似,采用两个指针,一个指针走一步,另一个走两步,然后如果有环,那么那个走两步必定会追上走一步的,也就是这两个节点会碰撞在一起。然后就是判断环的初始点。这里存在一个数学公式:

碰撞点P到连接点的距离 = 头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是环开始的连接点。有数学公式可以证明。

  寻找环的入口点: 当fast按照每次2步,slow每次一步的方式走,发现fast和slow重合,确定了单向链表有环路。接下来,让fast回到链表的头部,重新走,每次步长1,那么当fast和slow再次相遇的时候,就是环路的入口了。

证明:在fast和slow第一次相遇的时候,假定slow走了n步,环路的入口是在p步,那么

           slow走的路径: p+c = n; c为fast和slow相交点 距离环路入口的距离

           fast走的路径: p+c+k*L = 2*n; L为环路的周长,k是整数

          显然,如果从p+c点开始,slow再走n步的话,还可以回到p+c这个点。

          同时,fast从头开始走,步长为1,经过n步,也会达到p+c这点。

          显然,在这个过程中fast和slow只有前p步骤走的路径不同。所以当p1和p2再次重合的时候,必然是在链表的环路入口点上。

仔细理解下,还是可以懂得。

public class Solution
{
public ListNode detectCycle(ListNode head)
{
if(head == null || head.next== null)
return null;
if(head.next == head)
return head;
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null)
{
slow = slow.next;
fast = fast.next.next;
if(slow == fast)
break;
}
if(fast.next == null || fast.next.next == null)
return null;
slow = head;
while(slow != fast)
{
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: