一、问题描述
一个链表中包含环,请找出该链表的环的入口结点。
二、算法思想
1.判断链表是否为空;
2.判断是否存在环:用fast和slow两个指针,从head开始,一个走一步,一个走两步,如果最终到达同一个结点,则说明存在环;
3.寻找环的入口:假设入口结点距离头结点a个单位,fast和slow相遇在距离入口结点b个单位的位置,环剩下的长度为c,则有a+b+c+b = 2*(a+b) -> a = c 。因此,在重合时候,将fast置为head,再一步一步地走,当fast再次与slow重合时的结点即为入口结点。
三、代码实现
Python实现
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
# 1.判断链表是否为空
if pHead == None or pHead.next == None:
return None
# 2.定义fast和slow两个指针指向头结点
fast = slow = pHead
# 3.当指针指向不为空时
while(fast and fast.next):
# 慢指针走一步
slow = slow.next
# 快指针走两步
fast = fast.next.next
# 4.如果快、慢指针重合,则说明存在环
if slow == fast:
# 5.置fast为head结点从头走,slow位置不变
fast = pHead
# 6.当fast未与slow重合时,循环走
while(fast != slow):
# 此时fast和slow都一步一步走
fast = fast.next
slow = slow.next
# 7.直到fast与slow重合,重合的结点就是环的入口结点,返回该结点
return fast
return None
Java实现
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
//1.判断链表是否为空
if(pHead == null || pHead.next == null){
return null;
}
//2.定义fast指针和slow指针指向头结点
ListNode slow = pHead;
ListNode fast = pHead;
//3.指针指向不为空时
while(fast != null && fast.next != null){
//慢指针走一步
slow = slow.next;
//快指针走两步
fast = fast.next.next;
//4.如果快、慢指针重合,则说明存在环
if(slow == fast){
//5.置fast为head结点从头走,slow位置不变
fast = pHead;
//6.当fast未与slow重合时,循环走
while(fast != slow){
// 此时fast和slow都一步一步走
fast = fast.next;
slow = slow.next;
}
//7.直到fast与slow重合,重合的结点就是环的入口结点,返回该结点
return fast;
}
}
return null;
}
}
四、测试用例
(待测试)
功能测试:
1.没有环的链表
2.有环的链表
边界测试:
1.只有一个节点的链表
2.整个都是环的链表
极端测试:
链表头节点为null
五、拓展
https://blog.csdn.net/u012534831/article/details/74231581
如果要求环的长度,可以这样做:
当两者相遇之后,固定一个指针,让另一个指针行走一圈,使用count计数,如果两个指针相等(即相遇),则count即为环的长度。