141. Linked List Cycle
判断链表中是否有环
- 设置两个指针,一个快一个慢
- 每次慢的走一步,快的走两步,如果相遇就说明有环
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null)
return false;
ListNode p = new ListNode(0);
p.next = head;
ListNode fast = head.next, slow = p;
while (fast != null) {
if (fast == slow)
return true;
if (fast.next != null) {
fast = fast.next.next;
slow = slow.next;
} else
return false;
}
return false;
}
142. Linked List Cycle II
和上面的区别是如果有环,要返回环的入口结点,如果没环就返回空
- 先假设 入口结点是 entry,快慢指针相遇的结点是 meet
- 那么head到entry的距离是a,entry到meet的距离是b,环的长度是len
- 在快慢指针相遇时两个指针各走的路程:慢:a + b;快:a + n*len + b
- 因为快指针速度是慢的2倍,所以得到 2*(a+b) = a + b + n*len, 得到 a+b = n*len,得 a = n*len - b
- 即head 到 entry的长度 等于 环的n倍的长度 减去entry到 meet的长度
- 相当于说一个指针从head走到entry时,另一个指针从meet出发,走了n*len - b后也同时到达entry
public ListNode detectCycle(ListNode head) {
ListNode fast = head, slow = head;
while (fast.next == null || fast.next.next == null) {
fast = fast.next.next;
slow = slow.next;
//当快慢结点相遇时,慢结点继续从meet处出发,走了n*len - b后到达entry,而另一个结点从head出发也刚好到达entry
if (fast == slow) {
ListNode entry = head;
while (entry != slow) {
slow = slow.next;
entry = entry.next;
}
return entry;
}
}
return null;
}