剑指offer 复杂链表的复制
Posted qinduanyinghua
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer 复杂链表的复制相关的知识,希望对你有一定的参考价值。
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
1 struct RandomListNode 2 int label; 3 struct RandomListNode *next, *random; 4 RandomListNode(int x) : 5 label(x), next(NULL), random(NULL) 6 7 ;
解法一:
分两步: 1、复制原始链表节点,并用next链接起来。
2、设置每个节点的random指针。假设原始链表的某个节点N的random指向节点S,由于S在链表中可能在N的前面也可能在N的后面,所以要定位S的位置需要从原始链表的头结点开始找。如果从原始链表的头结点沿着next经过s步找到节点S,那么在复制链表上节点N‘的random(记为S‘)离复制链表的头结点的距离也是沿着next指针s步。用这种方法可以为复制链表上的每个节点设置random指针。
时间复杂度分析:对于一个有n个节点的链表,由于定位每个节点的random都需要从链表头结点开始经过 O(n)才能找到。因此总的时间复杂度为O(n2)
解法二:解法一的时间主要花费在定位节点的random上面。为此,我们分为两步:
第一,复制原始链表上的每一个节点N创建N‘,然后把这些创建出来的节点用next链接起来, 同时我们把<N, N‘>配对信息保存到一个哈希表中;
第二,设置每个节点的random。如果原始链表节点N的random为S, 那么在复制链表中N‘的random应该指向S‘. 第一步中,我们保存了<N, N‘>, <S, S‘>.
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 RandomListNode *res = new RandomListNode(0), *tmp = res, *pNode = pHead; //res是一个没有用的头结点。 15 map<RandomListNode*, RandomListNode*> mp; 16 while (pNode != NULL) 17 RandomListNode *node = new RandomListNode(pNode->label); //创建新节点N‘(node) 18 tmp->next = node; 19 tmp = node; 20 mp[pNode] = node; //建立哈希映射<N, N‘> 21 pNode = pNode->next; 22 23 tmp = pHead; 24 for (map<RandomListNode*, RandomListNode*>::iterator it = mp.begin(); it != mp.end(); it++) 25 //it->second: N‘, it->first: N, if->first->random: S, mp[S] = S‘ 26 it->second->random = mp[it->first->random]; 27 28 return res->next; 29 30 ;
以空间换时间, O(n)的空间复杂度,O(n)的时间复杂度
解法三:
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) 15 return NULL; 16 RandomListNode *pCurrent = pHead, *copyCurrent = NULL; 17 //复制一遍链表 18 while (pCurrent != NULL) 19 RandomListNode* node = new RandomListNode(pCurrent->label); 20 node->next = pCurrent->next; 21 pCurrent->next = node; 22 pCurrent = node->next; 23 24 25 pCurrent = pHead; 26 while (pCurrent != NULL) 27 copyCurrent = pCurrent->next; 28 if (pCurrent->random != NULL) 29 copyCurrent->random = pCurrent->random->next; 30 pCurrent = copyCurrent->next; 31 32 RandomListNode* pNode = pHead; 33 RandomListNode* pClonedHead = pNode->next; 34 RandomListNode* pClonedNode = pNode->next; 35 36 pNode->next = pClonedNode->next; 37 pNode = pClonedNode->next; 38 while (pNode != NULL) 39 pClonedNode->next = pNode->next; 40 pClonedNode = pNode->next; 41 pNode->next = pClonedNode->next; 42 pNode = pClonedNode->next; 43 44 return pClonedHead; 45 46 ;
以上是关于剑指offer 复杂链表的复制的主要内容,如果未能解决你的问题,请参考以下文章