sundeepblue
3/23/2014 - 3:16 AM

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