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;
}