题目
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
解法一
思路
快慢指针。这是个数学题。
按照快慢指针的方式,从head开始走。慢的指针走1步,快的指针走2步。如果有环,肯定会相遇。
假设从head到环入口长度为a,入口处到相遇处长度为b,相遇处到入口处长度为b。
如果相遇的话,快的指针一定比慢的指针夺走了几圈。
快的指针走了a+b+n(b+c),慢的指针走了a+b(慢的在圈里可能也绕了下,但快的一定比慢的多走了几圈)。而快的每次都比慢的多走了2步。有:
a+b+n(b+c)=2(a+b),整理后有,a = c + (n-1)(b+c)
也就是说,如果一个指针从head开始走,另一个指针从相遇位置开始走,那么这两个指针一定在入口处相遇。
代码
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
ListNode p = head;
while(p != slow) {
p = p.next;
slow = slow.next;
}
return p;
}
}
return null;
}
复杂度
- 时间复杂度:O(n)
- 空间复杂度:O(1)
解法二
思路
使用java的set结构,第一次遇到重复的就是入口点。
代码
public ListNode detectCycle(ListNode head) {
Set<ListNode> set = new HashSet<>();
ListNode p = head;
while (p != null) {
if (set.contains(p)) {
return p;
}
set.add(p);
p = p.next;
}
return null;
}
复杂度
- 时间复杂度:O(n)
- 空间复杂度:O(n)