题目来自编程之美
题目:如何找到环的入口?
分析:参考单链表面试题
代码:
/*在快慢指针相遇处,使用两个指针分别从头结点和碰撞处开始走,相遇点就是环入口点*/
ListNode* FindCycleEntry(ListNode* pHead)
{
assert(pHead != NULL);
ListNode* pFast = pHead;
ListNode* pSlow = pHead;
ListNode* pEntry = pHead;
while (pFast->m_pNext && pFast->m_pNext->m_pNext)
{
pFast = pFast->m_pNext->m_pNext;
pSlow = pSlow->m_pNext;
if (pFast == pSlow)//找到碰撞点
{
//查找环的入口结点
while (pEntry != pSlow)
{
pEntry = pEntry->m_pNext;
pSlow = pSlow->m_pNext;
}
return pEntry;
}
}
return NULL;
}
测试代码:
#include <iostream>
#include <assert.h>
using namespace std;
struct ListNode
{
int m_Data;
ListNode* m_pNext;
};
bool IsCycle(ListNode* pHead)
{
assert(pHead != NULL);
ListNode* pFast = pHead;
ListNode* pSlow = pHead;
while (pFast->m_pNext && pFast->m_pNext->m_pNext)
{
pFast = pFast->m_pNext->m_pNext;
pSlow = pSlow->m_pNext;
if (pFast == pSlow)
{
return true;
}
}
return false;
}
/*在快慢指针相遇处,使用两个指针分别从头结点和碰撞处开始走,相遇点就是环入口点*/
ListNode* FindCycleEntry(ListNode* pHead)
{
assert(pHead != NULL);
ListNode* pFast = pHead;
ListNode* pSlow = pHead;
ListNode* pEntry = pHead;
while (pFast->m_pNext && pFast->m_pNext->m_pNext)
{
pFast = pFast->m_pNext->m_pNext;
pSlow = pSlow->m_pNext;
if (pFast == pSlow)//找到碰撞点
{
//查找环的入口结点
while (pEntry != pSlow)
{
pEntry = pEntry->m_pNext;
pSlow = pSlow->m_pNext;
}
return pEntry;
}
}
return NULL;
}
void CreateList(ListNode** pHead,int nLen)//头指针使用指针的指针
{
assert(*pHead == NULL && nLen > 0);
ListNode* pCur = NULL;
ListNode* pNewNode = NULL;
for (int i = 0;i < nLen;i++)
{
pNewNode = new ListNode;
cin>>pNewNode->m_Data;
pNewNode->m_pNext = NULL;
if (*pHead == NULL)
{
*pHead = pNewNode;
pCur = *pHead;
}
else
{
pCur->m_pNext = pNewNode;
pCur = pNewNode;
}
}
}
/*把链表最后一个结点指向第三个结点*/
void CreateCycle(ListNode* pHead)
{
assert(pHead);
ListNode* pLastNode = pHead;
while (pLastNode->m_pNext)
{
pLastNode = pLastNode->m_pNext;
}
if (pHead->m_pNext && pHead->m_pNext->m_pNext)
{
pLastNode->m_pNext = pHead->m_pNext->m_pNext;
}
}
int main()
{
int nLen = 0;
bool bIsCircle = false;
ListNode* pHead = NULL;
ListNode* pHeadSec = NULL;
ListNode* pEntry = NULL;
//创建有环链表
cout<<"please input node num: ";
cin >> nLen;
CreateList(&pHead,nLen);//注意传参使用引用
CreateCycle(pHead);
bIsCircle = IsCycle(pHead);
if (bIsCircle)
{
cout<<"有环!"<<endl;
pEntry = FindCycleEntry(pHead);
cout<<"Entry Node: "<<pEntry->m_Data<<endl;
}
else
{
cout<<"无环"<<endl;
}
//创建无环链表
cout<<"please input node num: ";
cin >> nLen;
CreateList(&pHeadSec,nLen);//注意传参使用引用
bIsCircle = IsCycle(pHeadSec);
if (bIsCircle)
{
cout<<"有环!"<<endl;
pEntry = FindCycleEntry(pHeadSec);
cout<<"Entry Node: "<<pEntry->m_Data<<endl;
}
else
{
cout<<"无环"<<endl;
}
system("pause");
return 1;
}