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.
节点结构如下:
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
就是节点除了有next节点,还有一个指向随机节点的指针,需要深复制一个出来。主要有两种方法:
1、用一个unordered_map
来存储节点的随机关系
2、利用链表特点的O(1)额外空间进行复制:因为使用map的很容易理解,所以面试时经常会问能不能不用额外空间完成
一、unordered_map
Node* copyRandomList(Node* head) {
if (!head) return nullptr;
const auto head_cpy = head;
unordered_map<Node*, Node*> mmp;
while (head) { // 没有环
mmp[head] = new Node(head->val, nullptr, nullptr);
head = head->next;
}
head = head_cpy;
while(head) {
mmp[head]->next = mmp[head->next];
mmp[head]->random = mmp[head->random];
head = head->next;
}
return mmp[head_cpy];
}
二、利用链表特点
由于链表每个节点原本带有一个next
指针,指向下一个节点,可以利用链表特点,在每一个原有节点后边新增一个节点,用于复制前边的节点,然后依次给新的节点的 random 指针赋值(这个赋值非常容易 cur->next->random = cur->random->next,因为要指向新加的节点),最后跳过所有原有节点,就是新的复制出来的链表了。
Node* copyRandomList(Node* head) {
if (!head) return nullptr;
Node *cur = head;
while (cur) {
Node *t = new Node(cur->val);
t->next = cur->next;
cur->next = t;
cur = t->next;
}
cur = head;
while (cur) {
if (cur->random) cur->next->random = cur->random->next;
cur = cur->next->next;
}
cur = head;
Node *res = head->next;
while (cur) {
Node *t = cur->next;
cur->next = t->next;
if (t->next) t->next = t->next->next;
cur = cur->next;
}
return res;
}