劍指offer(26)——複雜鏈表的複製

題目


分析

       看到該問題,首先應該想到如果是單純的簡單的鏈表的複製,那麼很簡單,遍歷複製即可,就是考慮時間空間複雜性的問題。可是人家偏偏是個複雜鏈表,那麼複雜在哪?也不過就是每個結點多了一個可以指向鏈表中任意結點的一個指針域,我把它叫任意指針域。這樣想:複雜鏈表它怎麼着也是個鏈表,所以我們先像處理正常鏈表那樣,先不去管它的任意指針域,先複製出一條簡單鏈表;接着考慮如何將任意指針域的指向複製出來即可。
       這樣問題就簡單很多了,目標就是複製任意指針域。首先想到的方法應該是從第一個 結點開始找它的任意指針域的指向,找到後在新鏈表中按照找的過程來改變該新結點的任意指針域,每完成一個結點的任意指針域的複製就需要遍歷一遍該鏈表,大大增加了時間複雜度(O(n^2)假設有n個結點),顯然這樣的方法不可取。
再想一想爲什麼會出現上面的情況,仔細一想不難發現是因爲第一步在逐個複製鏈表結點時我們重新爲新鏈表開闢了額外的空間,這又增加了空間複雜度,有沒有不使用額外空間的方法來完成新鏈表的複製,答案是肯定的,畢竟咱們是程序員嘛。(哈哈哈)

代碼實現

/****************************************
分三步:
1、複製每個結點,將新結點連接在每個原結點後面
原鏈表:A->B->C->D
複製後的:A->A'->B->B'->C->C'->D->D'
2、修改任意指針域的指向
3、分離成兩個鏈表,返回複製的新鏈表即可
*****************************************/

struct ComplexListNode
{
	int m_nValue;
	ComplexListNode *m_pNext;   //指向下一個結點
	ComplexListNode *m_pSibling; //指向任意結點
};

//創建相應的結點鏈接在原節點後面
void CloneNodes(ComplexListNode *phead)
{
	ComplexListNode *pnode = phead;

	while(pnode != NULL)
	{
		ComplexListNode *pclone = new ComplexListNode();

		//創建的結點的數據域與原結點一致,任意指針域先置空,
		//下一步處理
		pclone->m_nValue = pnode->m_nValue;
		pclone->m_pSibling = NULL;

		//將原結點的next指針域指向複製出的結點
		pclone->m_pNext = pnode->m_pNext;
		pnode->m_pNext = pclone;

		//複製完一個結點並且連接好後再複製下一個結點
		//下一個結點是複製出的新結點的next域所指
		pnode = pclone->m_pNext;
	}

}

//處理任意結點域的指向
void ConnectSiblingNodes(ComplexListNode *phead)
{
	ComplexListNode *pnode = phead;

	while(pnode != NULL)
	{
		ComplexListNode *pclone = pnode->m_pNext;
		if(pnode->m_pSibling != NULL)
		{
			pclone->m_pSibling = pnode->m_pSibling->m_pNext;
		}
		pnode = pclone->m_pNext;
	}
}

//經過以上兩個函數操作,原鏈表和複製出的新鏈表
//連接在一起,現在將它們分開即就完成了複雜鏈表的複製
ComplexListNode *ReConnectListNode(ComplexListNode *phead)
{
	ComplexListNode *pnode = phead;
	ComplexListNode *pclonehead = NULL;
	ComplexListNode *pclonenode = NULL;

	if(pnode != NULL)
	{
		pclonehead = pclonenode = pnode->m_pNext;
		pnode->m_pNext = pclonenode->m_pNext;
		pnode = pnode->m_pNext;
	}

	while(pnode != NULL)
	{
		pclonenode->m_pNext = pnode->m_pNext;
		pclonenode = pclonenode->m_pNext;
		pnode->m_pNext = pclonenode->m_pNext;
		pnode = pnode->m_pNext;
	}

	return pclonehead;
}

ComplexListNode *ListClone(ComplexListNode *phead)
{
	if(phead == NULL)
		return phead;

	CloneNodes(phead);
	ConnectSiblingNodes(phead);

	return ReConnectListNode(phead);
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章