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.
struct ListNode {
int val;
ListNode *next, *rand
ListNode(int v) : val(v), next(NULL), rand(NULL) {}
}
ListNode *deep_copy_list_with_random_pointer(ListNode *head) {
if(!head) return NULL;
unordered_map<ListNode*, ListNode*> mp;
ListNode *p = head;
ListNode *dum = new ListNode(-1);
ListNode *q = dum;
// step1: deal with "next" pointers
while(p) {
ListNode *t = new ListNode(p->val);
q->next = t;
mp[p] = t;
q = q->next;
p = p->next;
}
// step2: deal with "rand" pointers
p = head;
q = dum->next;
while(p) {
if(p->rand == NULL) q->rand = NULL;
else q->rand = mp[p->rand];
p = p->next;
q = q->next;
}
/* concise version of step2
for(p = head; p; p = p->next) {
if(p->rand == NULL) mp[p]->rand = NULL;
else mp[p]->rand = mp[p->rand];
}
*/
return dum->next;
}
//==========================================
ListNode* clone_list_with_random_pointer(ListNode *head) {
if(!head) return NULL;
ListNode *clone_head = new ListNode(head->data);
unordered_map<ListNode*, ListNode*> mp;
mp[head] = clone_head;
ListNode *p1 = head->next, *p2 = clone_head; // did not use dummy node, so the code is a little bit longer
for(; p1; p1 = p1->next) {
p2->next = new ListNode(p1->data);
p2 = p2->next;
mp[p1] = p2;
}
for(ListNode *p1 = head; p1; p1 = p1->next) {
if(p1->random != NULL) {
mp[p1]->random = mp[p1->random];
}
}
return clone_head;
}