Sword finger Offer 35. Copy of complex linked list

Sword finger Offer 35. Copy of complex linked list
Please implement the copyRandomList function to copy a complex linked list. In a complex linked list, each node has a next pointer to the next node and a random pointer to any node or null in the linked list.

Example 1:

Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
Output: [[7,null],[13,0],[11,4],[10,2],[1,0]]
Example 2:

Input: head = [[1,1],[2,1]]
Output: [[1,1], [2,1]]
Example 3:

Input: head = [[3,null],[3,0],[3,null]]
Output: [[3,null],[3,0],[3,null]]
Example 4:

Input: head = []
Output: []
Explanation: the given linked list is null (null pointer), so null is returned.

Tips:

-10000 <= Node.val <= 10000
Node.random is empty (null) or points to a node in the linked list.
The number of nodes shall not exceed 1000.

Method 1: hash table
Using the query characteristics of hash table, consider building the key value pair mapping relationship between the original linked list node and the corresponding node of the new linked list, and then traverse the next and random reference points of each node of the new linked list.

Algorithm flow:
If the header node head is empty, null is returned directly;
Initialization: hash table dic, node cur points to the header node;
Copy linked list:
Create a new node and add key value pairs to dic (original cur node, new cur node);
cur traverses to the next node in the original linked list;
The reference to build a new linked list points to:
Build the next and random references of the new node;
cur traverses to the next node in the original linked list;
Return value: the header node dic[cur] of the new linked list;
Complexity analysis:
Time complexity O(N): traverse the linked list in two rounds, using O(N) time.
Spatial complexity O(N): the hash table dic uses additional space of linear size.

class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(head == nullptr) return nullptr;
        Node* cur = head;
        unordered_map<Node*, Node*> map;
        // 3. Copy each node and create a Map mapping of "original node - > new node"
        while(cur != nullptr) {
            map[cur] = new Node(cur->val);
            cur = cur->next;
        }
        cur = head;
        // 4. Build the next and random points of the new linked list
        while(cur != nullptr) {
            map[cur]->next = map[cur->next];
            map[cur]->random = map[cur->random];
            cur = cur->next;
        }
        // 5. Return the header node of the new linked list
        return map[head];
    }
};

Method 2: splicing + splitting
Consider building a spliced linked list of original node 1 - > new node 1 - > original node 2 - > new node 2 - >... So that you can find the new random pointing node corresponding to the new node while accessing the random pointing node of the original node.

Algorithm flow:
Copy each node to build a splicing linked list:

Let the original linked list be node1 → node2 →... And the constructed splicing linked list is as follows:

node1→node1new→node2→node2new →⋯

The random direction of each node of the new linked list:

When accessing the random pointing node cur.random of the original node cur, the random pointing node corresponding to the new node cur.next is cur.random.next.
Split the original / new linked list:

Set pre / cur to point to the original / new chain header node respectively, and perform pre.next = pre.next.next and cur.next = cur.next.next to separate the two linked lists.
Return the head node res of the new linked list.

Complexity analysis:
Time complexity O(N): three rounds of traversal of the linked list, using O(N) time.
Space complexity O(1): node reference variables use additional space of constant size.

class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(head == nullptr) return nullptr;
        Node* cur = head;
        // 1. Copy each node and build a splicing linked list
        while(cur != nullptr) {
            Node* tmp = new Node(cur->val);
            tmp->next = cur->next;
            cur->next = tmp;
            cur = tmp->next;
        }
        // 2. Build the random direction of each new node
        cur = head;
        while(cur != nullptr) {
            if(cur->random != nullptr)
                cur->next->random = cur->random->next;
            cur = cur->next->next;
        }
        // 3. Split two linked lists
        cur = head->next;
        Node* pre = head, *res = head->next;
        while(cur->next != nullptr) {
            pre->next = pre->next->next;
            cur->next = cur->next->next;
            pre = pre->next;
            cur = cur->next;
        }
        pre->next = nullptr; // Handle the original end node of the linked list separately
        return res;      // Return to the new chain header node
    }
};

Author: jyd
Link: https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/jian-zhi-offer-35-fu-za-lian-biao-de-fu-zhi-ha-xi-/

Tags: Algorithm data structure linked list

Posted on Sat, 11 Sep 2021 21:46:29 -0400 by genetheblue