题目:一个链表中包含环,如何找出环的入口结点?
例如,下图所示的链表中,环的入口结点就是结点3
完整测试程序:
#include <iostream>
using namespace std;
struct ListNode
{
int val;
ListNode* next;
};
//利用一快一慢两个指针,快指针速度是慢指针的两倍,找到两个指针在环中的相遇点
ListNode* MeetingNode(ListNode* pHead)
{
if (pHead == NULL) return NULL;
ListNode* fast = pHead;
ListNode* slow = pHead;
//如果无环,则fast先走到终点 ;当链表长度为奇数时,fast->Next为空 ;当链表长度为偶数时,fast为空
while( fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow) //如果有环,则fast会超过slow一圈再相遇
{
return fast;
}
}
return NULL;
}
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode* meetingNode = MeetingNode(pHead);
if (meetingNode == NULL)
return NULL;
// 求环中的节点个数
int nodesInLoop = 1;
ListNode* pNode1 = meetingNode;
while (pNode1->next != meetingNode)
{
pNode1 = pNode1->next;
++nodesInLoop;
}
// 结点指针pNode1先走nodesInLoop步
pNode1 = pHead;
for (int i = 0; i < nodesInLoop; ++i)
pNode1 = pNode1->next;
// 结点指针pNode1 和pNode2以相同的速度一起走
ListNode* pNode2 = pHead;
while (pNode1 != pNode2)
{
pNode1 = pNode1->next;
pNode2 = pNode2->next;
}
return pNode1;
}
ListNode* CreateListNode(int value)
{
ListNode* pNode = new ListNode();
pNode->val= value;
pNode->next = NULL;
return pNode;
}
void DestroyList(ListNode* pHead)
{
ListNode* pNode = pHead;
while (pNode != NULL)
{
pHead = pHead->next;
delete pNode;
pNode = pHead;
}
}
void ConnectListNodes(ListNode* pCurrent, ListNode* pNext)
{
if (pCurrent == NULL)
{
printf("Error to connect two nodes.\n");
exit(1);
}
pCurrent->next = pNext;
}
int main()
{
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);
ListNode* res = EntryNodeOfLoop(pNode1);
cout << "链表中环的入口结点是:"<<res->val<<endl;
system("pause");
DestroyList(res);
return 0;
}
ps:参考《剑指offer》中面试题56:链表中环的入口结点

本文介绍了一种通过快慢指针法找到链表中环入口结点的方法,并提供了完整的C++实现代码。该方法首先利用一快一慢两个指针找到环中的相遇点,接着计算环内的结点数量,最后通过同步移动两个指针来确定环的入口结点。
2008

被折叠的 条评论
为什么被折叠?



