题目描述:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
解题思路1:
首先根据next节点复制一个原链表,先不考虑random指向
再根据原链表每个节点,找到指向random的位置和首节点之间的距离,在复制链表中相同位置节点,random指向距离复制链表首节点相同距离位置的节点
如:原链表:next:1->2->3,random:1->3,2->3
首先根据next复制一个链表:1->2->3,然后发现1的random3指向距离首节点之后的两个距离的位置,则在复制的链表中1的random也指向首节点之后的两个的位置3,对所有节点相同处理。
这种思路较容易想到,但是时间复杂度为o(n^2),且实现起来很繁琐
解题思路2:
还是首先根据next复制一个链表,然后将原链表与复制链表的相同位置的节点构建一个map序列
如:原链表:next:a->b->c->d,random:a->c,b->d,c->d,d->NULL
根据next新建链表:a'->b'->c'->d',unordered_map<RandomListNode*,RandomListNode*>插入四个对,反别为(a,a'),(b,b'),(c,c'),(d,d')
则a‘的random指向为a的random指向c的map中的value,时间复杂度变为O(n)
参考源码:
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(pHead == NULL) return NULL;
unordered_map<RandomListNode*,RandomListNode*> pir;
RandomListNode* newhead = new RandomListNode(pHead->label);
pir.insert(make_pair(pHead,newhead));
RandomListNode* tmpbf = pHead->next;
RandomListNode* tmp = newhead;
while(tmpbf != NULL)
{
RandomListNode* node = new RandomListNode(tmpbf->label);
pir.insert(make_pair(tmpbf,node));
tmp->next = node;
tmp = tmp->next;
tmpbf = tmpbf->next;
}
RandomListNode* t = pHead;
while(t != NULL)
{
pir[t]->random = pir[t->random];
t = t->next;
}
return newhead;
}
};
解题思路3:
首先将原链表所有节点复制一个到节点之后:a->b->c,复制后为a->a->b->b->c->c
然后将所有节点node进行:node->next->random = node->random->next的操作,则可以将所有复制的节点指向正确的复制的random节点
再将原链表和复制链表拆分,返回复制链表的头。
注意:当涉及->next->next双指针时,一定注意->next为空的判断情况,否则会发生指针错误(当node->next为空再指向node->next->next时)
参考源码:
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(pHead == NULL) return NULL;
RandomListNode* headbf = pHead;
//将所有节点复制
while(headbf != NULL)
{
RandomListNode* t = headbf->next;
RandomListNode* tmp = new RandomListNode(headbf->label);
headbf->next = tmp;
tmp->next = t;
headbf = headbf->next->next;
}
//将所有复制的节点random指向正确位置
RandomListNode* headbf1 = pHead;
while(headbf1 != NULL)
{
if(headbf1->random != NULL)
{
headbf1->next->random = headbf1->random->next;
}
headbf1 = headbf1->next->next;
}
//将原链表和新链表分开
RandomListNode* newhead = pHead->next;
RandomListNode* tmp = pHead;
while(tmp->next != NULL)
{
RandomListNode* t = tmp->next;
tmp->next = t->next;
tmp = t;
}
return newhead;
}
};