題目:
請實現函數ComplexListNode* Clone(ComplexListNode* pHead),復制一個復雜鏈表。
在復雜鏈表中,每個結點除了有一個pNext指針指向下一個結點之外,還有一個pSibling指向鏈表中的任意結點或者NULL。
結點的定義如下:
struct ComplexListNode{
int val;
ComplexListNode* pNext;
ComplexListNode* pSibling;
};
思路:
方法1:
復制原始鏈表上的每一個結點,並通過pNext連接起來;然后再設置每個結點的pSibling指針。
假設原始鏈表中某個結點N的pSibling指針指向結點S,那么就需要從頭到尾遍歷查找結點S,如果從原始鏈表的頭指針開始,經過m步之后達到結點S,那么在復制鏈表中的結點N'的pSibling指針指向的結點也是距離復制鏈表s步的結點。通過這種辦法就可以為復制鏈表上的每個結點設置pSibling指針。
時間復雜度:O(N^2)
方法2:
方法1是通過鏈表查找來得到pSibling指針所指向的結點,實際上我們可以通過空間換取時間,將原始鏈表和復制鏈表的結點通過哈希表對應起來,這樣查找的時間就從O(N)變為O(1)。具體如下:
復制原始鏈表上的每個結點N創建N',然后把這些創建出來的結點用pNext連接起來。同時把<N,N'>的配對信息方法一個哈希表中;然后設置復制鏈表中的每個結點的pSibling指針,如果原始鏈表中結點N的pSibling指向結點S,那么在復制鏈表中,對應的N'應該指向S'。
時間復雜度:O(N)
方法3:
在不使用輔助空間的情況下實現O(N)的時間效率。
第一步:根據原始鏈表的每個結點N創建對應的N',然后將N‘通過pNext接到N的后面;
第二步:設置復制出來的結點的pSibling。假設原始鏈表上的N的pSibling指向結點S,那么其對應復制出來的N'是N->pNext指向的結點,同樣S'也是結點S->pNext指向的結點。
第三步:把長鏈表拆分成兩個鏈表,把奇數位置的結點用pNext連接起來的就是原始鏈表,把偶數位置的結點通過pNext連接起來的就是復制鏈表。
代碼:
1、Hash方法:
struct ComplexListNode{
int val;
ComplexListNode* pNext;
ComplexListNode* pSibling;
ComplexListNode():val(0),pNext(NULL),pSibling(NULL){};
};
typedef std::map<ComplexListNode*,ComplexListNode*> MAP;
ComplexListNode* CloneNodes(ComplexListNode* pHead,MAP &hashNode){
ComplexListNode* pNode=new ComplexListNode();
ComplexListNode* p=pNode;
ComplexListNode* tmp;
while(pHead!=NULL){
tmp=new ComplexListNode();
tmp->val=pHead->val;
p->pNext=tmp;
hashNode[pHead]=tmp;
pHead=pHead->pNext;
p=p->pNext;
}
return pNode->pNext;
}
void SetSiblings(ComplexListNode* pHead,ComplexListNode* pCopy,MAP &hashNode){
while(pCopy!=NULL){
pCopy->pSibling=hashNode[pHead->pSibling];
pCopy=pCopy->pNext;
pHead=pHead->pNext;
}
}
ComplexListNode* ComplexListCopy(ComplexListNode* pHead){
ComplexListNode* pCopy;
MAP hashNode;
pCopy=CloneNodes(pHead,hashNode);
SetSiblings(pHead,pCopy,hashNode);
return pCopy;
}
2、復制連接方法:
#include <iostream>
using namespace std;
struct ComplexListNode{
int val;
ComplexListNode* pNext;
ComplexListNode* pSibling;
ComplexListNode(int x):val(x),pNext(NULL),pSibling(NULL){};
};
void CloneNodes(ComplexListNode* pHead){
ComplexListNode* pNode=pHead;
ComplexListNode* pCloned;
while(pNode!=NULL){
pCloned=new ComplexListNode(pNode->val);
pNode->pNext=pCloned;
pCloned->pNext=pNode->pNext;
pNode=pCloned->pNext;
}
}
void ConnectSiblingNodes(ComplexListNode* pHead){
ComplexListNode* pNode=pHead;
ComplexListNode* pCloned;
while(pNode!=NULL){
pCloned=pNode->pNext;
if(pNode->pSibling!=NULL){
pCloned->pSibling=pNode->pSibling->pNext;
}
pNode=pCloned->pNext;
}
}
ComplexListNode* ReconnectNodes(ComplexListNode* pHead){
ComplexListNode* pNode=pHead;
ComplexListNode* pClonedHead=NULL;
ComplexListNode* pClonedNode=NULL;
if(pNode!=NULL){
pClonedHead=pClonedNode=pNode->pNext;
pNode->pNext=pClonedNode->pNext;
pNode=pNode->pNext;
}
while(pNode!=NULL){
pClonedNode->pNext=pNode->pNext;
pClonedNode=pClonedNode->pNext;
pNode->pNext=pClonedNode->pNext;
pNode=pNode->pNext;
}
return pClonedHead;
}
ComplexListNode* Clone(ComplexListNode* pHead){
CloneNodes(pHead);
ConnectSiblingNodes(pHead);
return ReconnectNodes(pHead);
}
在線測試OJ:
http://www.nowcoder.com/books/coding-interviews/f836b2c43afc4b35ad6adc41ec941dba?rp=1
AC代碼:
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
typedef std::map<RandomListNode*,RandomListNode*> MAP;
RandomListNode* CloneNextNode(RandomListNode* pHead,MAP &hashNode){
RandomListNode* pCopy=new RandomListNode(0);
RandomListNode* p=pCopy;
RandomListNode* tmp;
while(pHead!=NULL){
tmp=new RandomListNode(pHead->label);
p->next=tmp;
hashNode[pHead]=tmp;
p=p->next;
pHead=pHead->next;
}
return pCopy->next;
}
void setRandomNode(RandomListNode* pHead,RandomListNode* pCopy,MAP &hashNode){
while(pCopy!=NULL){
pCopy->random=hashNode[pHead->random];
pCopy=pCopy->next;
pHead=pHead->next;
}
}
RandomListNode* Clone(RandomListNode* pHead)
{
RandomListNode* pCopy;
MAP hashNode;
pCopy=CloneNextNode(pHead,hashNode);
setRandomNode(pHead,pCopy,hashNode);
return pCopy;
}
};
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
CloneNodes(pHead);
CloneRandom(pHead);
return ReConnectNodes(pHead);
}
void CloneNodes(RandomListNode* pHead){
RandomListNode* pCloned;
while(pHead!=NULL){
pCloned=new RandomListNode(pHead->label);
pCloned->next=pHead->next;
pHead->next=pCloned;
pHead=pCloned->next;
}
}
void CloneRandom(RandomListNode* pHead){
RandomListNode* pCloned;
while(pHead!=NULL){
pCloned=pHead->next;
if(pHead->random!=NULL){
pCloned->random=pHead->random->next;
}
pHead=pCloned->next;
}
}
RandomListNode* ReConnectNodes(RandomListNode* pHead){
RandomListNode* pClonedHead=NULL;
RandomListNode* pClonedNode=NULL;
RandomListNode* pNode=pHead;
if(pNode!=NULL){
pClonedHead=pClonedNode=pNode->next;
pNode->next=pClonedNode->next;
pNode=pNode->next;
}
while(pNode!=NULL){
pClonedNode->next=pNode->next;
pClonedNode=pClonedNode->next;
pNode->next=pClonedNode->next;
pNode=pNode->next;
}
return pClonedHead;
}
};
