Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Note: Do not modify the linked list.
Follow up:
Can you solve it without using extra space?
題目大意:
給定一個鏈表,如果該鏈表中含有環,則返回這個環開始的那個節點的地址,如果沒有環,則返回NULL.
原題鏈接: https://leetcode.com/problems/linked-list-cycle-ii/
這個題目接Linked List Cycle, 也是快慢指針的運用.示意圖如下:
如上圖, 在環的前面,長度爲a(即, 從頭結點開始,走a步到環的入口), 環的周長爲b(即,從環的入口開始,走b步回到入口處).
那麼快慢指針每次分別走2步和1步,設走了x步相遇,則:
則,可知:
那麼,相遇點從環入口處計數,已經走了
綜上,設快慢指針相遇點爲meet, 令一個指針爲p, p從頭指針出開始走, 每次走一步, meet也跟隨p每次走一步.那麼他們會在環的入口處相遇.
代碼如下:
// 有環的話,返回快慢指針相遇的地址;
// 無環的話,返回NULL
struct ListNode* judgeCycle(struct ListNode *head) {
int slowStep = 1;
int fastStep = 2;
struct ListNode* slow = head;
struct ListNode* fast = head;
while (true) {
for (int j = 0; j < fastStep; ++j) {
fast = fast->next;
if (NULL == fast) {
return NULL;
}
}
for (int i = 0; i < slowStep; ++i) {
slow = slow->next;
}
if (fast == slow) {
return fast;
}
}
}
struct ListNode *detectCycle(struct ListNode *head) {
if ((NULL == head) || (NULL == head->next)) {
return NULL;
}
struct ListNode* p = head;
struct ListNode* meet = judgeCycle(head);
if (NULL == meet) {
return NULL;
}
while (true) {
if (p == meet) {
return p;
}
p = p->next;
meet = meet->next;
}
}