【剑指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         }
View Code

 哈希表

暂无

逐节点伴生再拆分

 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 };
View Code

 

posted @ 2022-11-10 21:46  啊原来是这样呀  阅读(37)  评论(0)    收藏  举报