LeetCode Linked List Cycle II

题目:

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;
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值