方法一:哈希表
- 思路和判断链表是否有环一样,思路简单
package com.company.linked;
import java.util.HashSet;
import java.util.Set;
public class Solution2 {
public ListNode detectCycle(ListNode head) {
Set<ListNode> seen = new HashSet<ListNode>();
while (head != null) {
if (!seen.add(head)) {
return head;
}
head = head.next;
}
return null;
}
}
方法二:快慢指针
- 首先通过快慢指针找到链表相遇的点,这个点很关键
- 然后从这个点开始,slow指针逐个遍历,另外一个指针p从head开始逐个遍历,当两者相遇的时候,p指向的就是环的起点;这个逻辑需要画图且用代数化简得出,数学基础层面偏多;
- 参考解释:力扣
package com.company.linked;
public class Solution2_1 {
public ListNode detectCycle(ListNode head) {
if (head == null) {
return null;
}
ListNode slow = head, fast = head;
while (fast != null) {
slow = slow.next;
if (fast.next != null) {
fast = fast.next.next;
} else {
return null;
}
//从相遇点开始计算
if (fast == slow) {
ListNode ptr = head;
//双指针速度相同,走到相遇的时候,ptr就走到入环的第一个节点
while (ptr != slow) {
ptr = ptr.next;
slow = slow.next;
}
return ptr;
}
}
return null;
}
}