题目
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出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; } };