复杂链表的复制
思路:
时间复杂度为O(N)
第一步
按照顺序复制每一个结点,并且把复制过的结点放在被复制结点的next指针后面:
第二步
复制其中的随机指针
第三步
分开上下两个单链表:
1 /* 2 struct RandomListNode { 3 int label; 4 struct RandomListNode *next, *random; 5 RandomListNode(int x) : 6 label(x), next(NULL), random(NULL) { 7 } 8 }; 9 */ 10 class Solution { 11 public: 12 RandomListNode* Clone(RandomListNode* pHead) 13 { 14 if(pHead==NULL) return NULL; 15 //按照顺序复制每一个节点 16 //不用new,不同指针名指向的是同一个内存空间 17 RandomListNode* pnode = pHead;//初始化新的头结点,指向有效的源节点的内存空间 18 while(pnode){ 19 //用new开辟了一个新的内存空间,新指针指向新内存空间,只不过这个内存空间的值是相同的而已 20 RandomListNode* temp = new RandomListNode(pnode->label); 21 temp->next = pnode->next;//这里的pnode指针指向的就是源节点的内存空间,所以pnode->next == pHead->next 22 pnode->next = temp; 23 pnode = temp->next;//pnode此时为源链表的下一个结点 24 } 25 //上面这一步就是在源链表的基础上增加了新节点 26 //接下来复制random 27 //将源链表节点的random指向的节点复制给新链表的节点 28 pnode = pHead;//先回到原链表头结点 29 while(pnode){ 30 RandomListNode* temp = pnode->next;//pnode->next是新链表的头结点 31 //pnode->random是原链表节点random指向的节点,他的next是新链表中random指向的节点 32 if(pnode->random) temp->random = pnode->random->next; 33 pnode = temp->next; 34 } 35 //分解两个链表 36 pnode = pHead; 37 RandomListNode* temp; 38 RandomListNode* newhead = pHead->next; 39 while(pnode->next){ 40 temp = pnode->next; 41 pnode->next = temp->next; 42 pnode = temp; 43 } 44 return newhead; 45 } 46 };
方法二:
空间换时间,哈希表:
1 /* 2 struct RandomListNode { 3 int label; 4 struct RandomListNode *next, *random; 5 RandomListNode(int x) : 6 label(x), next(NULL), random(NULL) { 7 } 8 }; 9 */ 10 class Solution { 11 public: 12 RandomListNode* Clone(RandomListNode* pHead) 13 { 14 if(!pHead) return pHead; 15 unordered_map<RandomListNode*,RandomListNode*> m; 16 for(RandomListNode* p=pHead;p!=nullptr;p=p->next) 17 m[p] = new RandomListNode(p->label); 18 for(RandomListNode* p=pHead;p!=nullptr;p=p->next){ 19 m[p]->random = m[p->random]; 20 m[p]->next = m[p->next]; 21 } 22 return m[pHead]; 23 } 24 };