使用快慢指针。
第一次相遇,说明有环;第二次相遇,相遇点就是环入口。
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
class Solution {
// 快慢指针解决
// 两个指针相遇说明有环
// 快指针再回到头节点,两个指针同步走,再次相遇就是环入口
public ListNode entryNodeOfLoop(ListNode head) {
if(head == null || head.next == null){
// 空链表或者只有一个节点
return null;
}
ListNode slow = head;
ListNode fast = head;
// 1.判断是否有环
while(fast != null && fast.next != null){
// 慢指针走一步
slow = slow.next;
// 快指针走两步
fast = fast.next.next;
// 相遇,说明有环
if(slow == fast){
// 2.找到环的入口
// 将快指针移动头结点
fast = head;
while(slow != fast){
// 两个指针同步走
slow = slow.next;
fast = fast.next;
}
// 相遇就是环入口
return fast;
}
}
// 没有环
return null;
}
}
// 时间复杂度: O(n),快慢指针最多走两遍链表(一次判断环,一次找入口)
// 空间复杂度: O(1),只使用了两个指针