題目:
請實現函數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; } };