// 定義一個判斷連結串列是否有環的方法,接受一個頭節點作為引數
public boolean hasCycle(Node head) {
// 如果頭節點為空,直接返回false
if (head == null) {
return false;
}
// 定義快慢指標,初始化為頭節點
Node fast = head;
Node slow = head;
// 用一個迴圈來移動快慢指標
while (fast != null && fast.next != null) {
// 快指標每次移動兩個節點
fast = fast.next.next;
// 慢指標每次移動一個節點
slow = slow.next;
// 如果快慢指標相遇了,說明有環,返回true
if (fast == slow) {
return true;
}
}
// 如果快指標移動到了null,說明沒有環,返回false
return false;
}
舉個例子:
1 -> 2 -> 3 -> 4
^ |
| v
7 <- 6 <- 5
假設連結串列的長度是L,環的長度是n,環的入口節點距離頭節點的距離是a,快慢指標在環中相遇的節點距離環的入口節點的距離是b,那麼有以下關係:
假設從頭結點到環形入口節點的距離為x。 環形入口節點到fast指標與slow指標相遇節點距離為y。從相遇節點再到環形入口節點距離為z
public ListNode detectCycle(ListNode head) {
//如果連結串列為空或只有一個節點,直接返回null
if (head == null || head.next == null) {
return null;
}
//定義快慢指標
ListNode fast = head;
ListNode slow = head;
//遍歷連結串列,直到快指標遇到null或快慢指標相遇
while (fast != null && fast.next != null) {
//快指標走兩步,慢指標走一步
fast = fast.next.next;
slow = slow.next;
//如果快慢指標相遇,說明有環
if (fast == slow) {
//將快指標重新指向頭節點
fast = head;
//快慢指標都每次走一步,直到再次相遇
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
//返回相遇的節點,即入環的第一個節點
return fast;
}
}
//如果快指標遇到null,說明無環,返回null
return null;
}