您的位置:首页 > 职场人生

面试题56:链表中环的入口结点

2015-05-03 16:49 381 查看
题目:一个链表中包含环,如何找出环的入口结点?

首先,如果判断一个链表有环?

设置两个指针,一个指针一次走一步,一个指针一次走两步,如果链表有环,那么两个指针一定会相遇,而且是在环内相遇。

求环的入口结点:设置P1和P2两个指针指向头结点,如果环中有n个结点,指针P1现在链表上移动n步然后两个指针以相同的速度向前移动,当第二个指针指向环的入口点时,第一个指针已经围绕着环走了一圈,又回到了入口结点,即它们相遇的时候就是环的入口结点。

求环中结点个数:判断一个链表是否有环的时候,使用一快一慢两个指针,如果两个指针相遇则表明链表有环,两个指针相遇的结点一定是在环中,可以从这个结点出发,一边继续向前移动一边计数,当再次回到这个结点时,就可以得到环中结点数。

struct ListNode
{
int value;
ListNode * next;
};

//如果链表有环,找到一快一慢两个指针相遇的一个结点
ListNode* MeetingNode(ListNode* pHead)
{
if(pHead==NULL)
return NULL;

ListNode* pSlow=pHead->next;
if(pSlow==NULL)
return NULL;

ListNode* pFast=pSlow->next;

while(pFast!=NULL&&pSlow!=NULL)
{
if(pFast==pSlow)
return pFast;

pSlow=pSlow->next;

//pFast一次走两步
pFast=pFast->next;
if(pFast->next!=NULL)
pFast=pFast->next;
}
return NULL;
}

ListNode * EntryNodeOfLoop(ListNode * pHead)
{
ListNode * meetingNode=MeetingNode(pHead);
if(meetingNode==NULL)
return NULL;

//计算环中的结点数
int nodesInLoop=1;
ListNode* node1=meetingNode;
while(node1->next!=meetingNode)
{
node1=node1->next;
nodesInLoop++;
}

node1=pHead;//第一个指针指向头结点
ListNode* node2=pHead;//第二个指针也指向头结点

//先将node1走nodesInLoop步
for(int i=0;i<nodesInLoop;i++)
{
node1=node1->next;
}

//两个指针同时走,相遇的时候就是入口结点
while(node1!=node2)
{
node1=node1->next;
node2=node2->next;
}
return node1;
}


延伸:

判断两个链表是否相交:http://www.cppblog.com/zengwei0771/articles/172700.html

1.当两个链表都没有环的时候,如果两个链表相交,那么尾结点一定相同,判断它们的尾结点是否相同。

2.一个链表有环,另一个链表无环,则它们一定不相交。

3.当两个链表都有环的时候,两个链表环的入口结点为P1和P2

1)如果P1=P2一定相交

2)P1不等于P2

(1)P1不等于P2,判断它们是否在一个换,从P1开始向后遍历看是否能达到P2,如果能达到说明在一个环中,两个链表相交

(2)P1不等于P2,并且不在一个环,两个链表不想交。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: