题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
概念
复杂链表示例:方法一
可以分为两步来完成:
1、复制原始链表上的每一个结点,并用next链接起来;
2、设置每个结点的random 指针:由于链表中节点的random指针指向的节点可能在该节点之前,也可能在该节点之后,需要从头到尾的遍历链表来进行查找,然后连接起来,所以时间复杂度是O(N^2)。
方法二
方法一的时间花费主要在定位结点的random上,故我们可以对此优化:用空间换时间。方法还是可以分为两步:
1、复制原始链表上的每一个结点,并用next链接起来,同时创建一个map映射表:<N,N'>(原始结点,复制的结点),将两个链表中的节点映射起来,从而便于后续random指针的设置。
2、设置每个结点的random 指针:由于已经使用map结构将两个链表中的节点进行了映射,可以很方便的找到random指针应该指向的节点。用O(n)的空间消耗把时间复杂度由O(N^2)降到了O(n)。
扫描二维码关注公众号,回复:
153388 查看本文章
对应的代码如下:
/* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomListNode(int x) : label(x), next(NULL), random(NULL) { } }; */ class Solution { public: RandomListNode* Clone(RandomListNode* pHead) { if( pHead == NULL ) return NULL; unordered_map<RandomListNode*,RandomListNode*> record; RandomListNode* res = new RandomListNode(pHead->label); RandomListNode* p1 = pHead->next; RandomListNode* p2 = res; while( p1 ) { RandomListNode* temp = new RandomListNode(p1->label); p2->next = temp; record.insert( make_pair(p1,temp) ); p1 = p1->next; p2 = temp; } p1 = pHead; p2 = res; while( p1 ) { if( p1->random ) p2->random = record[p1->random]; p1 = p1->next; p2 = p2->next; } return res; } };
方法三
方法可以分为三步,以下图中的链表为例:
1、复制原始链表上的每一个结点N,创建对应的N’,并把N’放在N之后。如下图:
2、设置每个结点的random 指针。如果原始链表上的结点N的random指向S,则对应的复制结点N’(即节点N的next)的random指向S’(节点S的next)。如下图:
3、将长链表拆分成两个链表:把奇数位置的结点用pNext连接起来的就是原始链表,把偶数位置的结点通过pNext连接起来的就是复制链表。
代码如下:
/* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomListNode(int x) : label(x), next(NULL), random(NULL) { } }; */ class Solution { public: RandomListNode* Clone(RandomListNode* pHead) { if( pHead == NULL ) return NULL; RandomListNode* p = pHead; while( p ) //复制每个节点 { RandomListNode* temp = new RandomListNode(p->label); temp->next = p->next; p->next = temp; p = temp->next; } p = pHead; while( p ) //设置random指针 { if( p->random ) p->next->random = p->random->next; p = p->next->next; } p = pHead; RandomListNode* res = pHead->next; while( p ) //拆分 { RandomListNode* n = p->next; p->next = n->next; if( n->next ) n->next = n->next->next; p = p->next; } return res; } };