题目描述
- 一个链表中包含环,找出环的入口结点。
算法分析
- 设链表为1,2,3,...,n,...m 其中m指向n,形成环;可知链表长度为m,环长度为m-n+1,环的入口为n;
- 使得快慢指针均指向头结点,慢指针步长为1,快指针步长为2;两者相遇时,慢指针走了x步,此时块慢指针均指向1+x,即快指针比慢指针多走了一个环的长度,即1+x等于1+2x坐标,所以x等于环的长度m-n+1;
- 那么,此时快慢指针的位置为1+x=m-n+2,慢指针走到尾节点还需要n-2步,走到环入口,+1,还需要n-1步,若此时将某个节点从头结点走n-1步,则两者同时到达环入口节点。
提交代码:
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if (!pHead)
return nullptr;
ListNode* fastNode = pHead;
ListNode* slowNode = pHead;
while (fastNode && fastNode->next)
{
fastNode = fastNode->next;
fastNode = fastNode->next;
slowNode = slowNode->next;
if (fastNode == slowNode)
break;
}
if (!fastNode || !fastNode->next)
return nullptr;
fastNode = pHead;
while (fastNode != slowNode)
{
fastNode = fastNode->next;
slowNode = slowNode->next;
}
return fastNode;
}
};
测试代码:
// ==================== Test Code ====================
void Test(char* testName, ListNode* pHead, ListNode* entryNode)
{
if (testName != nullptr)
printf("%s begins: ", testName);
Solution s;
if (s.EntryNodeOfLoop(pHead) == entryNode)
printf("Passed.\n");
else
printf("FAILED.\n");
}
// A list has a node, without a loop
void Test1()
{
ListNode* pNode1 = CreateListNode(1);
Test("Test1", pNode1, nullptr);
DestroyList(pNode1);
}
// A list has a node, with a loop
void Test2()
{
ListNode* pNode1 = CreateListNode(1);
ConnectListNodes(pNode1, pNode1);
Test("Test2", pNode1, pNode1);
delete pNode1;
pNode1 = nullptr;
}
// A list has multiple nodes, with a loop
void Test3()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode3);
Test("Test3", pNode1, pNode3);
delete pNode1;
pNode1 = nullptr;
delete pNode2;
pNode2 = nullptr;
delete pNode3;
pNode3 = nullptr;
delete pNode4;
pNode4 = nullptr;
delete pNode5;
pNode5 = nullptr;
}
// A list has multiple nodes, with a loop
void Test4()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode1);
Test("Test4", pNode1, pNode1);
delete pNode1;
pNode1 = nullptr;
delete pNode2;
pNode2 = nullptr;
delete pNode3;
pNode3 = nullptr;
delete pNode4;
pNode4 = nullptr;
delete pNode5;
pNode5 = nullptr;
}
// A list has multiple nodes, with a loop
void Test5()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode5);
Test("Test5", pNode1, pNode5);
delete pNode1;
pNode1 = nullptr;
delete pNode2;
pNode2 = nullptr;
delete pNode3;
pNode3 = nullptr;
delete pNode4;
pNode4 = nullptr;
delete pNode5;
pNode5 = nullptr;
}
// A list has multiple nodes, without a loop
void Test6()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
Test("Test6", pNode1, nullptr);
DestroyList(pNode1);
}
// Empty list
void Test7()
{
Test("Test7", nullptr, nullptr);
}
int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
return 0;
}