7. [code] 複製帶隨機指針的鏈表
7.1 題目
給定一個鏈表,每個節點包含一個額外增加的隨機指針,該指針可以指向鏈表中的任何節點或空節點。
要求返回這個鏈表的深拷貝。
示例:
輸入:
{“KaTeX parse error: Expected '}', got 'EOF' at end of input: …":"1","next":{"id”:“2”,“next”:null,“random”:{“KaTeX parse error: Expected 'EOF', got '}' at position 9: ref":"2"}̲,"val":2},"rand…ref”:“2”},“val”:1}
解釋:
節點 1 的值是 1,它的下一個指針和隨機指針都指向節點 2 。
節點 2 的值是 2,它的下一個指針指向 null,隨機指針指向它自己。
提示:
你必須返回給定頭的拷貝作爲對克隆列表的引用。
難度:中等
7.2. 思路
假定上述的帶隨機指針的鏈表的類型稱爲Node類。
定義如下,包含值val,指向下一節點的指針next,和隨機指針random.
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node() {}
Node(int _val, Node* _next, Node* _random) {
val = _val;
next = _next;
random = _random;
}
};
*/
需要2個map,一個儲存原Node鏈表的每個節點的地址和序號,另一個存儲新Node鏈表的每個節點的地址和序號;由於新Node鏈表是原鏈表的拷貝,這裏的序號的相同的,因此,第二的map可以用vector代替。
先創建一個新Node鏈表,則可以將這一新鏈表的每個節點的地址push入上述的vector,即這一vector儲存了新Node鏈表的每個節點地址;
再遍歷原Node鏈表,將原Node鏈表的每個節點的地址和序號分別儲存入map的KEY和VALUE;
對新的Node鏈表需要兩個操作:
- 每個節點next指針相連;
- 每個節點,如果存在ranndom,則random的指向;
7.3. 代碼
class Solution {
public:
Node* copyRandomList(Node* head) {
if (!head) return NULL;
//定義<Node*, int>類型的map和<Node*>類型的vector
std::map<Node*, int> node_map;
std::vector<Node*> node_vec;
//新鏈表的每個節點的地址push入上述的vector
Node* ptr = head;
int i=0;
while(ptr){
//vector存入新Node鏈表的地址
node_vec.push_back(new Node(ptr->val));
//map存入原Node鏈表的地址和序號
node_map[ptr]=i;
//下一個節點
ptr = ptr->next;
i++;
}
//將0加入node_vec的最末,確保後續node_vec最後一個節點的next指針指向不出錯
node_vec.push_back(0);
//遍歷原Node鏈表,
ptr = head;
i=0;
while(ptr){
//每個節點next指針相連
node_vec[i]->next = node_vec[i+1];
//每個節點,如果存在ranndom,則random的指向
if (ptr->random){
int id = node_map[ptr->random]; //該節點random指向的節點的序號
node_vec[i]->random = node_vec[id];
}
ptr = ptr->next;
i++;
}
return node_vec[0];
}
};
提交到oj上有錯誤
下面這個方法簡直神仙方法,太棒了:
先寫一下代碼
class Solution{
public:
Node* copyRandomList(Node* head){
if (!head) return nullptr;
/* 將拷貝的節點接在原節點後面,再繼續接下一個原節點 */
for (Node* cur = head; cur != nullptr; ){
Node* node = new Node(cur->val);
node->next = cur->next;
cur->next = node;
cur = node->next;
}
/* 確定每個新節點的random指向 */
for (Node* cur = head; cur != nullptr;) {
if (cur->random != NULL){
cur->next->random = cur->random->next;
}
else{
cur->next->random = NULL;
}
cur = cur->next->next;
}
/* 分離兩個鏈表 */
Node dummy(-1);
Node* new_node = &dummy;
for (Node* cur = head; cur != nullptr; ){
new_node->next = cur->next;
if(cur->next != NULL){
cur->next = cur->next->next;
}
else{
cur->next = NULL;
}
new_node = new_node->next;
cur = cur->next;
}
return dummy.next;
}
};
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
for (RandomListNode* cur = head; cur != nullptr; ) {
RandomListNode* node = new RandomListNode(cur->label);
node->next = cur->next;
cur->next = node;
cur = node->next;
}
for (RandomListNode* cur = head; cur != nullptr; ) {
if (cur->random != NULL)
cur->next->random = cur->random->next;
cur = cur->next->next;
}
RandomListNode dummy(-1);
for (RandomListNode* cur = head, *new_cur = &dummy; cur != nullptr; ) {
new_cur->next = cur->next;
new_cur = new_cur->next;
cur->next = cur->next->next;
cur = cur->next;
}
return dummy.next;
}
};