
这个题的难点就在于,复制时,需要找到对应的新的链表,比如10指向1,我们要和新链表的1对应上,就必须要用哈希表做记录,或者用一些手法。
解法一:哈希表
考虑建一个只有next的列表,其实比较简单,但是random要求我们随机访问,所以要存一下老节点对应的新节点。
cpp
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
Node *dummy = new Node(0), *p = head, *p2 = dummy;
map<Node*, Node*> s;
while(p)
{
Node *n = new Node(p->val);
p2->next = n;
s[p] = n;
p2 = p2->next;
p = p->next;
}
p = head, p2 = dummy->next;
while(p)
{
if(p->random)
{
auto n2 = s[p->random];
p2->random = n2;
}
p = p->next;
p2 = p2->next;
}
return dummy->next;
}
};
解法二:零空间
既然做链表题,就得要求零空间复杂度,这才是难点,但是这个算法也是真麻烦
首先,先做原数组修改,每个节点后面加上一个复制,这样就可以用核心语句 p->next->random = p->random->next; 来对所有新节点的random节点进行赋值(最难得一步)
然后就是链表分离(最恶心的一步)由于新老链表完全耦合,需要同时进行新老链表的分离操作,新链表用dummy取出,老链表用作遍历,细节比较多
cpp
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if(!head)return nullptr;
Node *p = head, *tmp;
while(p)
{
tmp = p->next;
p->next = new Node(p->val);
p->next->next = tmp;
p = tmp;
}
p = head;
while(p)
{
if(p->random)
{
p->next->random = p->random->next;
}
p = p->next->next;
}
Node *dummy = new Node(0);
p = dummy;
Node *p1 = head;
while(p1)
{
p->next = p1->next;
p = p->next;
p1->next = p1->next->next;
p1 = p1->next;
}
return dummy->next;
}
};