剑指offer:链表中环的入口节点

题目:如果一个链表中包含环,找出环的入口节点。

思考:如果一个链表有环,用一个指针遍历将永远也走不到尽头。若用两个指针遍历:快指针每次走一步,慢指针每次走两步。如果快指针走到了链表的末尾都没有追上慢指针,则没有环。如果快指针追上了慢指针,则有环。

如图

一个带环的链表,环内节点个数为4.

步骤

a) 指针pfast,pslow初始化时都指向链表的第一个节点。

b) 由于环中有4个节点,所以pfast指针先走4步。

c) 快指针,慢指针以相同速度向前移动,直到它们相遇。

再思考

如何得到环中节点的数目?

1)两个指针,快指针一次走两步,慢指针一次走一步,如果俩指针相遇,则说明有环,且相遇的指针一定在环中。

2)设定一个指针从相遇点开始遍历环内节点并计数,待再次回到这个节点时,就可以得到环内节点个数。

如何找到入口节点?

1)两个指针从头遍历,让快指针先走“节点的个数”步,然后快慢指针同时走,待相遇时,即是入口节点。

Node* JudgeIfCircle(Node* pHead)//判断是否有环
{	
	if(pHead == NULL || pHead->pnext == NULL)
	{
		return NULL;
	}

	Node* pfast = pHead->pnext->pnext;
	Node* pslow = pHead->pnext;

	while(pslow != pfast)
	{
		pfast = pfast->pnext->pnext;
		pslow = pslow->pnext;
	}

	return pfast;
}

Node* EntryNode(Node* pHead)
{
	Node* meetNode = JudgeIfCircle(pHead);

	if (meetNode == NULL)
	{
		return NULL;
	}
	
	Node* pCur= meetNode;
	
	/*int count = 0;
	while (pCur != meetNode)//循环进不去
	{
		pCur = pCur -> pnext;
		count++;
	}*/

	int count = 1;

	while(pCur->pnext!= meetNode)//查找环中几个节点
	{
		pCur = pCur->pnext;
		count++;
	}

	Node* pfast = pHead->pnext;
	Node* pslow = pfast;//使两个指针指向第一个节点

	for (int i = 0; i < count; i++)//快指针先走count步
	{
		pfast = pfast->pnext;
	}

	while (pslow != pfast)
	{
		pfast = pfast->pnext;
		pslow = pslow->pnext;
	}

	return pfast;
}

猜你喜欢

转载自blog.csdn.net/free377096858/article/details/84565787