题目:
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
思路:
1.得到相遇点:
设置两个节点,一个fast(快节点)和slow(慢节点),假设fast速度是slow的两倍,则那在相遇之前,fast走的距离为slow的2倍。
设置一个slow和fast的相遇点,假设起始点head与入口点的距离为X,相遇点到入口点的距离为Y,圆环的长度为C
所以可知两者相遇之时:
slow 距离:X+C-Y
fast 距离:X+C+C-Y
由于fast速度是slow的两倍,路程也应该是slow的两倍。
SO: 2*(X+C-Y) = X+C+C-Y
解得:X = Y
这说明头节点到环形链表的入口点的距离与相遇点到入口点的距离是一样的。
此时,我们可以通过快慢指针来找到两者的相遇点,相遇后,判断其是否为环形链表,
如果是环形链表的话,fast and fast.next 节点一定不为空
如果不是环形链表,如下图:
走到最后他们的next节点一定为空,返回null 结束。
如果是环形链表的话,我们只剩最后一个步骤,找到入口点:
将slow设置为头节点,让位于相遇点的fast节点和位于head的slow节点开始遍历,由于两者要走的距离都是一样的,当slow == fast时,即为入口点,返回即可!
实现步骤:
1.同过快慢指针找到两者的相遇点。
//1.找到两者相遇点:
ListNode fast = head;
ListNode slow = head;
while(fast!=null && fast.next!=null)
{
fast = fast.next.next;
slow = slow.next;
if(slow == fast)
{
break;
}
}
2.判断是否有环:无环:即相遇后 fast 或fast.next为null。
//判断是否有环;
if(fast == null || fast.next == null)
{
return null; //没有环
}
3.有环,则将slow指针置为head,和fast进行遍历直到相遇的点,即为入环的第一个节点
/有环:
slow = head;
while(slow!=fast)
{
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
这个问题到这里就已经结束了,觉得有用的宝字们来个三联吧