题目描述
输入一个复杂链表(每个结点中有结点值,以及两个指针,一个指向下一个结点,另一个特殊指针random指向一个随机结点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意:输出结果中不要返回此参数中的结点引用,否则判断题程序会直接返回空)
解题思路
先复制链表的结点值和指向下一个结点的指针,最后再复制random指针。查找random指针分为两种:一种是每次都从头开始遍历查找,时间复杂度为 O(n^2);另一种是空间换时间,复制结点值和指向下一个结点指针的同时,创建一个hash表来存放新旧复杂指针的对应关系,只要一步就可以查找到random,时间复杂度为O(n)。
将复制的过程分为以下三步:
- 复制复杂指针的,结点值和next指针。把复制的结点直接插入到原结点的后面;
- 设置复制出来新结点的random指针。因为新旧链表是前后对应关系,所以也可以一步直接找到random;
- 拆分链表。
步骤示例图:
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| struct RandomListNode { int label; struct RandomListNode *next, *random; RandomListNode (int x): label(x), next(NULL), random(NULL) {} };
class Solution { public: void CloneNodes(RandomListNode* pHead) { RandomListNode* pNode = pHead; while (pNode != NULL) { RandomListNode* pCloned = new RandomListNode(0); pCloned->label = pNode->label; pCloned->next = pNode->next; pCloned->random = NULL; pNode->next = pCloned; pNode = pCloned->next; } } void FindrandomNodes(RandomListNode* pHead) { RandomListNode* pNode = pHead; while (pNode != NULL) { RandomListNode* pCloned = pNode->next; if (pNode->random != NULL) pCloned->random = pNode->random->next; pNode = pCloned->next; } } RandomListNode* ReconnectNodes(RandomListNode* pHead) { RandomListNode* pNode = pHead; RandomListNode* pClonedHead = NULL; RandomListNode* pClonedNode = NULL; 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; } RandomListNode* Clone(RandomListNode* pHead) { CloneNodes(pHead); FindrandomNodes(pHead); return ReconnectNodes(pHead); } };
|
参考博文链接:https://cuijiahua.com/blog/2017/12/basis_25.html