【剑指offer】10.复杂链表的复制
总目录:
1.问题描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)。 下图是一个含有5个结点的复杂链表。图中实线箭头表示next指针,虚线箭头表示random指针。为简单起见,指向null的指针没有画出。

示例:
输入:{1,2,3,4,5,3,5,#,2,#}
输出:{1,2,3,4,5,3,5,#,2,#}
解析:我们将链表分为两段,前半部分{1,2,3,4,5}为ListNode,后半部分{3,5,#,2,#}是随机指针域表示。
以上示例前半部分可以表示链表为的ListNode:1->2->3->4->5
后半部分,3,5,#,2,#分别的表示为
1的位置指向3,2的位置指向5,3的位置指向null,4的位置指向2,5的位置指向null
2.问题分析
1使用vector记录输入链表中每个节点的random指向的序号,施加在新链表上,需要提取两个方法用来按节点获取索引和按索引获取节点
2哈希表法?目前未看到可靠的实现
3逐节点伴生,节点映射都是旧节点的下一个,映射完再拆开
3.代码实例
vector+2个方法辅助
 
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 13 int GetTgtNodeIndex(RandomListNode* pHead, RandomListNode* pTgt) { 14 int tgtIndex = -1; 15 if (!pTgt) { 16 return tgtIndex; 17 } 18 19 int indexCounter = 0; 20 while (pHead) { 21 indexCounter++; 22 if (pHead == pTgt) { 23 tgtIndex = indexCounter; 24 break; 25 } 26 27 pHead = pHead->next; 28 } 29 return tgtIndex; 30 } 31 32 RandomListNode* GetTgtNode(RandomListNode* pHead, int index) { 33 if (index < 1) { 34 return NULL; 35 } 36 37 int indexCounter = 0; 38 while (pHead) { 39 indexCounter++; 40 if (indexCounter == index) { 41 return pHead; 42 } 43 pHead = pHead->next; 44 } 45 return NULL; 46 } 47 48 RandomListNode* Clone(RandomListNode* pHead) { 49 if (!pHead) { 50 return pHead; 51 } 52 53 //复制节点,并记录random信息 54 RandomListNode* inputNode = pHead; 55 RandomListNode* newHead = (RandomListNode*)malloc(sizeof(RandomListNode)); 56 memset(newHead, 0, sizeof(RandomListNode)); 57 RandomListNode* pCur = newHead; 58 59 vector<int> ranTgtIndexVec; 60 int tgtNodeIndex = 0; 61 62 while (inputNode) { 63 //复制数据 64 pCur->label = inputNode->label; 65 66 //记录tgt坐标 67 tgtNodeIndex = GetTgtNodeIndex(pHead, inputNode->random); 68 ranTgtIndexVec.push_back(tgtNodeIndex); 69 70 //是否有下一个节点 71 if (inputNode->next) { 72 pCur->next = (RandomListNode*)malloc(sizeof(RandomListNode)); 73 memset(pCur->next, 0, sizeof(RandomListNode)); 74 } else { 75 break; 76 } 77 78 //后移 79 inputNode = inputNode->next; 80 pCur = pCur->next; 81 } 82 83 //逐个按索引对ramdom赋值 84 pCur = newHead; 85 int curNodeINdex = 0; 86 while (pCur) { 87 pCur->random = GetTgtNode(newHead, ranTgtIndexVec[curNodeINdex++]); 88 pCur = pCur->next; 89 }
哈希表
暂无
逐节点伴生再拆分
 
1 class Solution { 2 public: 3 RandomListNode* Clone(RandomListNode* pHead) { 4 if(!pHead) return pHead; // 为空则返回 5 RandomListNode* cur = pHead; 6 while(cur){ 7 RandomListNode* tmp = new RandomListNode(cur->label); // 拷贝节点 8 tmp->next = cur->next; 9 cur->next = tmp; 10 cur = tmp->next; 11 } 12 13 RandomListNode *old = pHead, *clone = pHead->next, *ret = pHead->next; 14 while(old){ 15 clone->random = old->random == NULL ? NULL : old->random->next; // 处理拷贝节点的随机指针 16 if(old->next) old = old->next->next; // 注意特判空指针,最后一个节点没有->next->next 17 if(clone->next) clone = clone->next->next; // 注意特判空指针,最后一个节点没有->next->next 18 } 19 20 old = pHead, clone = pHead->next; 21 while(old){ // 拆分链表 22 if(old->next) old->next = old->next->next; 23 if(clone->next) clone->next = clone->next->next; 24 old = old->next; 25 clone = clone->next; 26 } 27 28 return ret; 29 } 30 };
 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号