[Linked lists and arrays] Lintcode 105. Copy linked lists with random pointers

Lintcode 105. Copy a linked list with random pointers

Title description:
Given a linked list, each node contains an additional random pointer that can point to any node in the linked list or an empty node. Return a deep copy of the linked list.

Problem-solving ideas:
1. One way to achieve this is to store the mapping relationship between the new and old nodes through the map data structure, and then deep copy the linked list.

2. The biggest challenge of this problem is to use O(1) space to achieve, that is, to achieve the constant level of extra space. At this time, the mapping relationship stored in the map is extra space consumption, not O(1) space implementation.
How to realize it without map?
It is said that this is a question that Microsoft took a long time ago, and most people can't think of this realization idea.
The basic idea is to first convert the original linked list 1->2->3->3->4->NULL
to =>, 1->1'->2->2'->3->3'->4->4'...
that is, use the next node in the original linked list to store the mapped new node, and use the next of the original node next to store the original next. The random node is also mapped from this mapping relationship, so that because 1', 2'... these values ​​are the last values ​​to be returned, the goal of O(1) space can be achieved without additional space consumption.

Tips:
Constant-level extra space: generally means that in addition to the value passed in and the last return value, there can be no other orders of magnitude space consumption (for example, you new a very long (n) array), of course It is still possible to create several variables at the constant level.

The following code shows two methods (using map and O(1) space implementation), and two languages ​​(C++ and Java) implementation:
(1) C++:

// 1、Map方法
/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     RandomListNode *next, *random;
 *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
    
    
public:
    /**
     * @param head: The head of linked list with a random pointer.
     * @return: A new head of a deep copy of the list.
     */
    RandomListNode *copyRandomList(RandomListNode *head) {
    
    
        map<RandomListNode*, RandomListNode*> old2new_Map;//新旧节点之间的映射关系
        RandomListNode *dummy = new RandomListNode;
        RandomListNode *prev = dummy;
        RandomListNode *newNode;
        while (nullptr != head) {
    
    
            if (old2new_Map.count(head)) {
    
    
                newNode = old2new_Map[head];
            } else {
    
    
                RandomListNode *node = new RandomListNode(head->label);
                old2new_Map[head] = node;
                newNode = node;
            }
            prev->next = newNode;
            
            if (nullptr != head->random) {
    
    
                if (old2new_Map.count(head->random)) {
    
    
                    newNode->random = old2new_Map[head->random];
                } else {
    
                    
                    RandomListNode *randNode = new RandomListNode(head->random->label);
                    old2new_Map[head->random] = randNode;
                    newNode->random = randNode;
                }
            } else {
    
    
                newNode->random = nullptr;                
            }
            prev = newNode;
            head = head->next;
        }
        
        return dummy->next;
    }
};



// 2、O(1)空间实现
/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     RandomListNode *next, *random;
 *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
    
    
public:
    /**
     * @param head: The head of linked list with a random pointer.
     * @return: A new head of a deep copy of the list.
     */
    RandomListNode *copyRandomList(RandomListNode *head) {
    
    
        // write your code here
        if(!head)
            return head;
        for(auto p=head;p;){
    
    
            auto n=new RandomListNode(p->label);
            n->next=p->next;
            p->next=n;
            p=n->next;
        }
        for(auto p=head;p;p=p->next->next)
            if(p->random)
                p->next->random=p->random->next;
        RandomListNode* nh=head->next,*tail=nh;
        while(tail){
    
    
            head=head->next=head->next->next;
            tail=tail->next=head?head->next:nullptr;
        }
        return nh;
    }
};

(2)Java:

//HashMap version
public class Solution {
    
    
    public RandomListNode copyRandomList(RandomListNode head) {
    
    
        if (head == null) {
    
    
            return null;
        }

        HashMap<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>();
        RandomListNode dummy = new RandomListNode(0);
        RandomListNode pre = dummy, newNode;
        while (head != null) {
    
    
            if (map.containsKey(head)) {
    
    
                newNode = map.get(head);
            } else {
    
    
                newNode = new RandomListNode(head.label);
                map.put(head, newNode);
            }
            pre.next = newNode;

            if (head.random != null) {
    
    
                if (map.containsKey(head.random)) {
    
    
                    newNode.random = map.get(head.random);
                } else {
    
    
                    newNode.random = new RandomListNode(head.random.label);
                    map.put(head.random, newNode.random);
                }
            }

            pre = newNode;
            head = head.next;
        }

        return dummy.next;
    }
}

/*第一遍扫的时候巧妙运用next指针, 开始数组是1->2->3->4  。 然后扫描过程中 先建立copy节点 1->1`->2->2`->3->3`->4->4`, 然后第二遍copy的时候去建立边的copy, 拆分节点, 一边扫描一边拆成两个链表,这里用到两个dummy node。第一个链表变回  1->2->3 , 然后第二变成 1`->2`->3`  */
//No HashMap version
public class Solution {
    
    
    private void copyNext(RandomListNode head) {
    
    
        while (head != null) {
    
    
            RandomListNode newNode = new RandomListNode(head.label);
            newNode.random = head.random;
            newNode.next = head.next;
            head.next = newNode;
            head = head.next.next;
        }
    }

    private void copyRandom(RandomListNode head) {
    
    
        while (head != null) {
    
    
            if (head.next.random != null) {
    
    
                head.next.random = head.random.next;
            }
            head = head.next.next;
        }
    }

    private RandomListNode splitList(RandomListNode head) {
    
    
        RandomListNode newHead = head.next;
        while (head != null) {
    
    
            RandomListNode temp = head.next;
            head.next = temp.next;
            head = head.next;
            if (temp.next != null) {
    
    
                temp.next = temp.next.next;
            }
        }
        return newHead;
    }

    public RandomListNode copyRandomList(RandomListNode head) {
    
    
        if (head == null) {
    
    
            return null;
        }
        copyNext(head);
        copyRandom(head);
        return splitList(head);
    }
}

Guess you like

Origin blog.csdn.net/phdongou/article/details/113818930