A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
本题出现了一个新的链表结点结构,结点有两个指针域,一个指向下一个结点,一个指向链表中的随机结点或者NULL。要求对该链表进行深复制(就是 copy 出来的副本与原本是完全独立,互不影响。改动原来的,不会影响副本,反之亦然。)
有两种解法
第一种解法:
按照原链表next的顺序依次创建结点、建立next关系,同时把原结点与新结点的一一对应关系保存到一个hash_map中。然后根据这个hash_map,在第二次循环时建立random关系。这种方法的时间复杂度是O(n),空间复杂度也是O(n)。
当然也可以用一次迭代完成,每次循环既建立next关系又建立random关系。 若果random 指向的结点在副本链表中还未创建,则创建并建立random关系;否则,直接连接副本结点的random关系。
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
std::unordered_map<RandomListNode*, RandomListNode*> map;
RandomListNode preHead(0);
for (RandomListNode *next = &preHead; head; next = next->next, head = head->next) {
if (map[head] == NULL) {
RandomListNode* node = new RandomListNode(head->label);
map[head] = node;
}
next->next = map[head];
if (head->random && map[head->random] == NULL) {
RandomListNode* node = new RandomListNode(head->random->label);
map[head->random] = node;
}
map[head]->random = map[head->random];
}
return preHead.next;
}
};
第二种解法:
三次迭代。原链表:1-2-3-4-5
第一次迭代,按照原链表next的顺序依次创建结点并插入到原结点之后。以此替代hash_map建立原结点、新结点之间的对应关系。即链表变为:1-1'-2-2'-3-3'-4-4'-5-5'
第二次迭代,建立random关系。cp 为副本结点,org 为原结点,那么有以下关系:cp->random = org->rndom->next>
第三次迭代,将链表拆分成两个。
这种方法的时间复杂度是O(n),(额外的空间复杂度是O(1))空间复杂度是O(n)。
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if (!head) return NULL;
RandomListNode *cur = head;
while (cur)
{
RandomListNode *cp = new RandomListNode(cur->label);
cp->next = cur->next;
cur->next = cp;
cur = cur->next->next;
}
cur = head;
while (cur)
{
if (cur->random)
{
cur->next->random = cur->random->next;
}
cur = cur->next->next;
}
cur = head;
RandomListNode *next, *copy;
RandomListNode *copyHead = cur->next;
while (cur)
{
next = cur->next->next;
copy = cur->next;
cur->next = next;
if (next)
{
copy->next = next->next;
}
else
{
copy->next = NULL;
}
cur = cur->next;
}
return copyHead;
}
};