题目来自编程之美
题目: 判断有环单链表的链表长度
思路: 统计第一个结点到碰撞点之间结点个数 + 统计环中结点个数,具体见单链表面试题
代码
/*
思路:统计第一个结点到碰撞点之间结点个数 + 统计环中结点个数
1、先找到碰撞点
2、利用碰撞点,找到环入口点,同时统计第一个结点到碰撞点之间结点个数
3、利用碰撞点或者环入口点,在环中转圈,统计环中结点个数
*/
int GetNodeCountOfList(ListNode* pHead)
{
assert(pHead != NULL);
ListNode* pFast = pHead;
ListNode* pSlow = pHead;
ListNode* pEntry = pHead;
int nCountOfBeforeEntry = 0; //统计第一个结点到碰撞点之间结点个数
int nCountOfCycle = 1; //统计环中结点个数
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;
nCountOfBeforeEntry++;
}
//统计环中结点个数
pSlow = pFast;
pFast = pFast->m_pNext;
while (pFast != pSlow)
{
pFast = pFast->m_pNext;
nCountOfCycle++;
}
return nCountOfBeforeEntry + nCountOfCycle;
}
}
return 0;
}
测试代码
#include <iostream>
#include <assert.h>
using namespace std;
struct ListNode
{
int m_Data;
ListNode* m_pNext;
};
/*
思路:统计第一个结点到碰撞点之间结点个数 + 统计环中结点个数
1、先找到碰撞点
2、利用碰撞点,找到环入口点,同时统计第一个结点到碰撞点之间结点个数
3、利用碰撞点或者环入口点,在环中转圈,统计环中结点个数
*/
int GetNodeCountOfList(ListNode* pHead)
{
assert(pHead != NULL);
ListNode* pFast = pHead;
ListNode* pSlow = pHead;
ListNode* pEntry = pHead;
int nCountOfBeforeEntry = 0; //统计第一个结点到碰撞点之间结点个数
int nCountOfCycle = 1; //统计环中结点个数
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;
nCountOfBeforeEntry++;
}
//统计环中结点个数
pSlow = pFast;
pFast = pFast->m_pNext;
while (pFast != pSlow)
{
pFast = pFast->m_pNext;
nCountOfCycle++;
}
return nCountOfBeforeEntry + nCountOfCycle;
}
}
return 0;
}
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;
}
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;
//创建有环链表
cout<<"please input node num: ";
cin >> nLen;
CreateList(&pHead,nLen);//注意传参使用引用
CreateCycle(pHead);
bIsCircle = IsCycle(pHead);
if (bIsCircle)
{
cout<<"有环!"<<endl;
cout<<"环中结点个数: "<<GetNodeCountOfList(pHead)<<endl;
}
else
{
cout<<"无环"<<endl;
}
//创建无环链表
cout<<"please input node num: ";
cin >> nLen;
CreateList(&pHeadSec,nLen);//注意传参使用引用
bIsCircle = IsCycle(pHeadSec);
if (bIsCircle)
{
cout<<"有环!"<<endl;
cout<<"环中结点个数: "<<GetNodeCountOfList(pHeadSec)<<endl;
}
else
{
cout<<"无环"<<endl;
}
system("pause");
return 1;
}