【leetcode】141/142Linked List Cycle(Floyd判圈算法)

题目概述:

141:给定一个单链表,判断是否有环

142:给定一个单链表,判断是否有环,若有返回环的起始结点,若没有返回null


考虑用O(1)空间复杂度的算法实现,用到了Floyd判圈算法(也叫龟兔赛跑算法)。

Floyd判圈算法是一个可以在有限状态机、迭代函数或者链表上判断是否存在环,以及求出该环的起点与长度的算法。

原理是如果存在环,那么从同一个起点出发,同时以不同速度前进的2个指针必定会在某个时刻相遇。


首先判断是否有环:

本题中可以采用一个慢指针和一个快指针,慢指针每次前进一个结点,快指针每次前进两个结点,速度差为1,若快指针后续结点为空,则说明没有环,若能够相遇则有环。

速度差为1保证了如果存在环则必定可以相遇,若速度差为其他值,速度差与环长恰有某种关系时可能永远无法相遇。

设环长为n,当慢指针指向环的起始结点时,快指针与慢指针相差最大结点数为n-1(快指针指向起始节点的后续结点),类似追及问题,慢指针也只要再移动n-1次则能够与快指针相遇,也就保证了时间复杂度为O(n)


接着考虑如何找到环的起始结点:

设链表头结点经过x个结点到达环的起始结点,再经过y个结点快慢指针相遇,环长为n

经过上面的讨论可以知道慢指针不会围绕环再走一圈,根据两指针速度关系有:2(x+y)=x+y+kn,即x+y=kn,k为正整数

相遇后令其中一个指针重新指向链表头结点,另一个指针位置不变,令两指针以相同速度移动,再次相遇时指向的结点就是环的起始结点

(头结点向后移动x个结点为环起始结点,x+y=kn即从环起始结点后y个结点处(最初相遇的结点)出发,经过x步可以重新回到环起始结点)


【leetcode】141/142Linked List Cycle(Floyd判圈算法)_第1张图片

你可能感兴趣的:(leetcode,算法与数据结构,面试笔试题)