题目大意:深拷贝一个链表,链表除了含有next指针外,还包含一个random指针,该指针指向字符串中的某个节点或者为空。
节点定义为:
struct RandomListNode {
int label;
RandomListNode *next, *random;
RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
};
假设原始链表如下,细线表示next指针,粗线表示random指针,没有画出的指针均指向NULL:
算法1:我们在构建新链表的节点时,保存原始链表的next指针映射关系,并把指针做如下变化(蓝色为原始链表节点,紫红色为新链表节点):
然后在上图的基础上进行如下两步
1、构建新链表的random指针:比如new1->random = new1->random->random->next, new2->random = NULL, new3-random = NULL, new4->random = new4->random->random->next
2、恢复原始链表:根据最开始保存的原始链表next指针映射关系恢复原始链表
该算法时间空间复杂度均为O(N)
算法2:该算法更为巧妙,不用保存原始链表的映射关系,构建新节点时,指针做如下变化,即把新节点插入到相应的旧节点后面:
同理分两步
1、构建新节点random指针:new1->random = old1->random->next, new2-random = NULL, new3-random = NULL, new4->random = old4->random->next
2、恢复原始链表以及构建新链表:例如old1->next = old1->next->next, new1->next = new1->next->next
该算法时间复杂度O(N),空间复杂度O(1)
下面分别为算法1和算法2代码:
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head)
{
// Note: The Solution object is instantiated only once and is reused by each test case.
if(head == NULL)return NULL;
std::map<RandomListNode *,RandomListNode *> oldlistMap;
RandomListNode *result = new RandomListNode(head->label) ;
RandomListNode *pold = head, *pnew = result;
pnew->random = pold;
//pold->next = pnew;
RandomListNode* poldPre = pold, *pnewPre = pnew;
while(pold->next != NULL)
{
//保存old list的next指针
oldlistMap.insert(std::map<RandomListNode*,
RandomListNode*>::value_type(pold, pold->next));
pold = pold->next;
poldPre->next = pnew;
pnew = new RandomListNode(pold->label);
pnewPre->next = pnew;
pnew->random = pold;
poldPre = pold;
pnewPre = pnew;
}
pold->next = pnew;//设置old list最后一个节点
//设置new list的random指针
pnew = result;
while(pnew != NULL)
{
if(pnew->random->random)
pnew->random = pnew->random->random->next;
else pnew->random = NULL;
pnew = pnew->next;
}
//恢复old list的next指针
pold = head;
for(int i = 1; i <= oldlistMap.size(); i++)
{
pold->next = oldlistMap[pold];
pold = pold->next;
}
pold->next = NULL;//old list 最后一个节点
return result;
}
};
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head)
{
// Note: The Solution object is instantiated only once and is reused by each test case.
if(head == NULL)return NULL;
RandomListNode *result = NULL;
RandomListNode *pold = head, *pnew = result, *poldNext = NULL;
do
{
poldNext = pold->next;
pnew = new RandomListNode(pold->label);
pold->next = pnew;
pnew->next = poldNext;
if(result == NULL)
result = pnew;
pold = poldNext;
}while(pold);
//设置new list的random指针
pold = head;
while(pold)
{
if(pold->random)
pold->next->random = pold->random->next;
pold = pold->next->next;
}
//恢复old list 和new list
pold = head;
pnew = result;
while(pnew->next)
{
pold->next = pnew->next;
pold = pold->next;
pnew->next = pold->next;
pnew = pnew->next;
}
pold->next = NULL;
pnew->next = NULL;
return result;
}
};
9.18更新
------------------
思路:
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(!head) return NULL;
unordered_map<RandomListNode*, RandomListNode*> ht;
RandomListNode *p1 = head;
RandomListNode *p2 = new RandomListNode(head->label);
ht[head] = p2;
while(p1) {
if(p1->next) {
if(ht.count(p1->next))
p2->next = ht[p1->next];
else {
p2->next = new RandomListNode(p1->next->label);
ht[p1->next] = p2->next;
}
}
if(p1->random) {
if(ht.count(p1->random))
p2->random = ht[p1->random];
else {
p2->random = new RandomListNode(p1->random->label);
ht[p1->random] = p2->random;
}
}
p1 = p1->next;
p2 = p2->next;
}
return ht[head];
}
};