題目
給一個鏈表,若其中包含環,請找出該鏈表的環的入口結點,否則,輸出null。
思路一
1、用快慢指針從頭節點開始,快指針一次走兩步,慢指針一次走一步,若有環,必然會相遇。
2、將其中一個指針重置到頭節點,另一個指針指向相遇節點,然后以相同速度走,再次相遇必然是環的入口節點
證明:
當相遇時
然后以相同速度走
class Solution { public: ListNode* EntryNodeOfLoop(ListNode* pHead) { ListNode* meetingNode = MeetingNodeOfLoop(pHead); if (meetingNode == nullptr) return nullptr; //找到了鏈表中的環 while (pHead != meetingNode){ pHead = pHead->next; meetingNode = meetingNode->next; } return meetingNode; } //尋找環中相遇的節點 ListNode* MeetingNodeOfLoop(ListNode* pHead) { if (pHead == nullptr || pHead->next == nullptr) return nullptr; ListNode *slow = pHead->next; ListNode *fast = slow->next; while (slow && fast) { if (slow == fast) return fast; else { slow = slow->next; fast = fast->next; if (fast) fast = fast->next; else return nullptr; } } return nullptr; } };
思路二
當允許改變鏈表時,可以使用斷鏈法。
class Solution { public: ListNode* EntryNodeOfLoop(ListNode* pHead) { if (!MeetingNodeOfLoop(pHead)) return nullptr; // 斷鏈法 ListNode* slow = pHead, *fast = slow->next; while (fast) { slow->next = nullptr; slow = fast; fast = fast->next; } return slow; } //尋找環中相遇的節點 ListNode* MeetingNodeOfLoop(ListNode* pHead) { if (pHead == nullptr || pHead->next == nullptr) return nullptr; ListNode *slow = pHead->next; ListNode *fast = slow->next; while (slow && fast) { if (slow == fast) return fast; else { slow = slow->next; fast = fast->next; if (fast) fast = fast->next; else return nullptr; } } return nullptr; } };