1. 程式人生 > >劍指offer:連結串列中環的入口節點

劍指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;
}