*leetcode 138 in cpp

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.


The problem is to maintain the connection between the copy and its next,  also the copy and its random pointer. 

Say we have list 1->2->3->4. 

If we want to construct the deep copy of only the next's pointer, without considering the random pointer, then we probably follow the procedure at our first thought:

cur = 1, make copy = 1

list:    1->2->3->4

copy: 1

cur = 2, make copy 2

list:    1->2->3->4


copy: 1->2

....

...

cur = 4, make copy 4

list:    1->2->3->4

copy: 1->2->3->4. 

But when there are random pointers, things would change a lot. Say we have 

list:    1->2->3->4

random: 1->3, 2->3. 
If we follow the procedure above:

cur = 1, make copy 1, make random copy 3
list:      1->2->3->4,  random:         1->3, 2->3
copy:   1                   random copy:1->3

cur = 2, make copy 2, make random copy 4
list:      1->2->3->4,  random:         1->3, 2->3
copy:   1->2                   random copy:1->3, 2->3

But if we think about it a little bit, we would notice random copy 3 for node 2 does not have the same address as the random copy 4 for node 1.

We create a new random pointer at node 1 and a new random pointer at node 2. Even though they are with the same value, they do not have the same address. 

At final step we would have a copy of 1->2->3->4, where 3's next is 4. But at this time, 1's random node 3 would not link to node 4. Neither would 2's random node. 

So when we construct random node for node 2, we should move 2's random pointer to 1's random pointer rather than making a new pointer. 

So the problem would be how to remember the random pointer address, and how to move he random pointer to a previously created random pointer. 


Solution 1: O(n^2)

First construct a copy list of the orginal list. 

For current node A,  we find the distance, d, between A's random pointer away and A in the original list. Then we come back to the copy list, link current node to the node with distance d away form it. 

This is based on the assumption that in the copy list, distance between a node and its random pointer would be the same. 

Code 1: naive copy

class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        return naive_copy(head);
    }
    
    RandomListNode *naive_copy(RandomListNode *head){
        RandomListNode * temp = new RandomListNode(0);
        RandomListNode * pre = temp; 
        RandomListNode * cur = head; 
        while(cur){
            pre->next = new RandomListNode(cur->label);
            pre = pre->next;
            cur = cur->next; 
        }
        pre = temp->next;
        cur = head;
        while(pre && cur){
            RandomListNode *r = cur->random; 
            if(rand){
                RandomListNode *pre_fast = pre;
                RandomListNode *cur_fast = cur; 
                while(cur_fast != r){
                    if(!cur_fast){
                        cur_fast = head; 
                        pre_fast = temp->next; 
                    }
                    else{
                        cur_fast = cur_fast->next;
                        pre_fast = pre_fast->next;
                    }
                }
                pre->random = pre_fast; 
            }
            cur = cur->next; 
            pre = pre->next; 
        }
        return temp->next;
    }
};
Solution 2:

We use a map to store a node and its copy. map[node] = its copy

When a node A has random pointer to node B, point A copy's random pointer  (map[nodeA]->random) to A's random pointer's copy (map[ node A's random pointer]). 

Code:

class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        return copy(head);
    }
    RandomListNode *copy(RandomListNode *head){
        if(!head) return NULL;
        map<RandomListNode*, RandomListNode*> mapp; 
        RandomListNode *cur = head; 
        mapp[head] = new RandomListNode(head->label);
        while(cur){
            //link current node's copy with its next
            if(cur->next){
                if(mapp.find(cur->next) == mapp.end()) 
                    mapp[cur->next] = new RandomListNode(cur->next->label);
                mapp[cur]->next = mapp[cur->next]; 
            }
            //construct current node's copy with its random
            if(cur->random){
                if(mapp.find(cur->random) == mapp.end())
                    mapp[cur->random] = new RandomListNode(cur->random->label);
                mapp[cur]->random = mapp[cur->random];
            }
            cur = cur->next; 
        }
        return mapp[head];
    }
    
};



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章