剑指offer-复杂链表的复制
描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)。 下图是一个含有5个结点的复杂链表。图中实线箭头表示next指针,虚线箭头表示random指针。为简单起见,指向null的指针没有画出。
求解思路:
- 第一个循环先构建非随机链(即只考虑next指针),并用map记录label与新链表各节点的映射
- 第二个循环根据map,完善随机指针。
代码:
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 // 然后依次检验每个节点的随机指针,读取val,通过val确定新链的随机指针 15 // 改进:在构建非随机链表时,新建map映射 val和random(这里记录节点) 16 std::map<int,RandomListNode*> lm; 17 RandomListNode* newHead=NULL; 18 RandomListNode* tail; // 记录尾节点 19 // 完成非随机链表的构建 20 RandomListNode* ergNode=pHead; 21 while(ergNode!=nullptr){ 22 RandomListNode* rn=new RandomListNode(ergNode->label); 23 if(newHead==nullptr){ 24 newHead=rn; 25 }else{ 26 tail->next=rn; 27 } 28 tail=rn; 29 // 构建label和node的映射 30 // lm.insert(pair<int,RandomListNode*>(rn->label,rn)); 31 lm[rn->label]=rn; 32 ergNode=ergNode->next; 33 } 34 // 再用一个循环完成随机链表的构建 35 ergNode=pHead; // 遍历原有链表 36 RandomListNode* repNode=newHead; // 补充现有链表 37 while(ergNode!=nullptr){ 38 if(ergNode->random!=nullptr){ 39 repNode->random=lm[ergNode->random->label]; 40 int f=1; 41 } 42 ergNode=ergNode->next; 43 repNode=repNode->next; 44 } 45 return newHead; 46 } 47 };
心之所愿,永不相忘