題目描述
輸入一個複雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果爲複製後複雜鏈表的head。(注意,輸出結果中請不要返回參數中的節點引用,否則判題程序會直接返回空)
題目分析
複雜問題簡單化,將該問題拆分成三步來實現,就簡單多了。
1、遍歷鏈表,複製鏈表中的每個結點,並將複製的結點插入到該結點的後面。例如,原鏈表爲A->B->C, 遍歷完畢後,鏈表變爲A->A'->B->B'->C->C',其中A‘,B',C'是結點A,B,C的複製結點。
看圖中,藍色箭頭爲next指針:
複製結點後:
void CloneNode(RandomListNode* pHead)
{//克隆節點
RandomListNode* pNode = pHead;
while(pNode != NULL)
{
RandomListNode* qNode = new RandomListNode(0);
qNode ->label = pNode -> label;
qNode -> next = pNode -> next;
//qNode -> random = pNode -> random;
pNode ->next = qNode;
pNode = qNode -> next;
}
}
2、爲複製結點的random指針賦值
如果原結點的random指針指向的是結點B,那麼將複製結點的random指針指向結點B的複製結點B'。
圖中黑色箭頭爲random指針:
複製結點的random指針賦值後:
void CloneRandom(RandomListNode* pHead)
{//克隆節點關係
RandomListNode* pNode = pHead;
RandomListNode* qNode = pHead;
while(pNode != NULL)
{
qNode = pNode -> next;
if(pNode -> random != NULL)
qNode -> random = pNode -> random -> next;
pNode = qNode -> next;
}
}
3、將鏈表的原始結點與複製結點分割至兩個鏈表,使原始結點構成一個鏈表,複製結點構成一個鏈表。
RandomListNode* ResitNode(RandomListNode* pHead)
{//斷開新舊鏈表
RandomListNode* pNode = pHead;
RandomListNode* newHead = NULL;
RandomListNode* newNode = NULL;
if(pNode != NULL)
{
newHead = newNode = pNode -> next;
pNode -> next = newNode -> next;
pNode = pNode -> next;
}
while(pNode != NULL)
{
newNode -> next = pNode -> next;
newNode = newNode -> next;
pNode -> next = newNode -> next;
pNode = pNode -> next;
}
return newHead;
}
4、運行
RandomListNode* Clone(RandomListNode* pHead)
{
CloneNode(pHead);
CloneRandom(pHead);
return ResitNode(pHead);
}