【leetcode】-142-环形链表-求入环点-双指针

【双指针】

fast指针每次走两步,slow指针每次走一步,如果没有环slow和fast永远不会相遇。

为什么fast和slow指针会在环中相遇?

fast比slow先入环,如果两个指针要相遇,只可能是这样一种情况

可以理解为,fast指针对slow指针的追赶是相对速度1,追赶过程中是一个节点一个节点走的,所以最终一定能相遇。

相遇时:

  • slow走过的路程:x + y + n(y+z), n代表slow绕了n圈
  • fast走过的路程:x + y + m(y+z),m代表fast饶了m圈
  • m > n

因为fast速度是slow两倍:

  • 2(x + y + n(y + z)) = x + y + m(y + z)
  • x + y = (m - 2n)(y + z)
  • x = (m - 2n)(y + z) - y
  • y + z就是1圈,假设 o = m-2n,o是一个正整数,那么 x = o(y + z) -y
  • 如果o = 1,那么 x = z。
  • 如果o > 1,那么 x = (o-1)(y+z) + y + z - y, x = (o-1)(y+z) + z,即x的长度为o-1圈加上z

然而我们并不关心转了几圈,只关心入环点是谁,所以可以只看o=1的情况,此时x=z

  • 在相遇点设置一个指针index2,从头结点设置一个指针index1,两个指针同步移动,由于x=z,所以两个指针相遇的点就是入环点!

ps:实际上第一次相遇点肯定是在slow指针的第一圈内,但是这需要数学归纳法的推导,有点难以理解,所以就用了上述推导,设置了slow转的圈数n。

 ListNode *detectCycle(ListNode *head) {
  	
    ListNode *fast = head, *slow = head;

	while (fast!=NULL&&fast->next!= NULL)
	{
		fast = fast->next->next;//快指针一次走两步
		slow = slow->next;//满指针一次走一步

		if (slow == fast) 
		{
			ListNode *index2 = fast, *index1 = head;//一个指针从相遇点开始,一个指针从头开始

			while (index1 != index2)
			{
				index1 = index1->next;
				index2 = index2->next;
			}

			return index1;
		}
	}

	return NULL;//如果循环结束还没有返回值,说明链表没有环
    }

猜你喜欢

转载自blog.csdn.net/qq_39328436/article/details/113676957