|
1 | 1 | ---
|
| 2 | + |
2 | 3 | id: copy-list-with-random-pointer
|
3 |
| -title: Copy List with Random Pointer |
4 |
| -sidebar_label: 0138 Copy List with Random Pointer |
| 4 | +title: Copy List With Random Pointer |
| 5 | +level: medium |
| 6 | +sidebar_label: Copy List With Random Pointer |
5 | 7 | tags:
|
| 8 | + - Hash Table |
| 9 | + - Linked List |
6 | 10 | - Java
|
7 | 11 | - Python
|
8 | 12 | - C++
|
9 |
| - - JavaScript |
10 |
| - |
11 |
| -description: "This is a solution to the Copy List with Random Pointer problem on LeetCode." |
| 13 | +description: "This document provides solutions for the Copy List With Random Pointer problem on LeetCode." |
| 14 | + |
12 | 15 | ---
|
13 | 16 |
|
14 | 17 | ## Problem Description
|
15 | 18 |
|
16 |
| -A linked list of length n is given such that each node contains an additional random pointer, which could point to any node in the list, or `null`. |
17 |
| - |
18 |
| -Construct a deep copy of the list. The deep copy should consist of exactly `n` brand new nodes, where each new node has its value set to the value of its corresponding original node. Both the `next` and `random` pointer of the new nodes should point to new nodes in the copied list such that the pointers in the original list and copied list represent the same list state. None of the pointers in the new list should point to nodes in the original list. |
| 19 | +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. |
19 | 20 |
|
20 |
| -For example, if there are two nodes `X` and `Y` in the original list, where `X.random --> Y`, then for the corresponding two nodes `x` and `y` in the copied list, `x.random --> y`. |
| 21 | +Construct a deep copy of the list. |
21 | 22 |
|
22 | 23 | ### Examples
|
23 | 24 |
|
24 | 25 | **Example 1:**
|
25 |
| - |
26 |
| - |
27 |
| - |
28 | 26 | ```
|
29 | 27 | Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
|
30 | 28 | Output: [[7,null],[13,0],[11,4],[10,2],[1,0]]
|
31 | 29 | ```
|
32 | 30 |
|
33 | 31 | **Example 2:**
|
34 |
| - |
35 |
| - |
36 |
| - |
37 | 32 | ```
|
38 | 33 | Input: head = [[1,1],[2,1]]
|
39 | 34 | Output: [[1,1],[2,1]]
|
| 35 | +``` |
40 | 36 |
|
| 37 | +**Example 3:** |
| 38 | +``` |
| 39 | +Input: head = [[3,null],[3,0],[3,null]] |
| 40 | +Output: [[3,null],[3,0],[3,null]] |
41 | 41 | ```
|
42 | 42 |
|
43 |
| ---- |
| 43 | +### Constraints: |
44 | 44 |
|
45 |
| -## Solution for Copy List with Random Pointer |
| 45 | +- The number of nodes in the list is in the range [0, 1000]. |
| 46 | +- `-10000 <= Node.val <= 10000` |
| 47 | +- Node.random is null or is pointing to a node in the linked list. |
46 | 48 |
|
| 49 | +--- |
47 | 50 |
|
48 |
| -### Understand the Problem: |
| 51 | +## Approach to Solve the Copy List with Random Pointer Problem |
49 | 52 |
|
50 |
| -Create a deep copy of a linked list where each node has a `next` and a `random` pointer. The new list should be identical in structure to the original, but with all new nodes. Ensure the `random` pointers in the new list accurately reflect the original's `random` pointer relationships. |
| 53 | +To create a deep copy of a linked list with an additional random pointer, follow these steps: |
51 | 54 |
|
52 | 55 | ### Approach
|
53 | 56 |
|
54 |
| -1. **Interweaving Nodes**: Create and insert new nodes immediately after each original node, forming an interwoven list. |
55 |
| -2. **Assigning Random Pointers**: Set the `random` pointers of the new nodes based on the `random` pointers of the original nodes. |
56 |
| -3. **Separating Lists**: Restore the original list and extract the copied list by adjusting the `next` pointers of both original and new nodes. |
| 57 | +1. **Create Clones Adjacent to Original Nodes:** |
| 58 | + - Iterate through the original list and create a new node for each original node. Insert this new node right next to the original node. This way, each original node will have its clone right next to it. |
| 59 | + |
| 60 | +2. **Assign Random Pointers to Cloned Nodes:** |
| 61 | + - Iterate through the list again. For each original node, if it has a random pointer, set the random pointer of the clone node to point to the clone of the node that the original node’s random pointer is pointing to. This can be achieved because the clone of any node `A` is next to `A`. |
| 62 | + |
| 63 | +3. **Restore the Original List and Extract the Cloned List:** |
| 64 | + - Iterate through the list once more to restore the original list by separating the original nodes from their clones. Extract the cloned list by linking the cloned nodes together. |
57 | 65 |
|
58 | 66 | #### Code in Different Languages
|
59 | 67 |
|
60 |
| -<Tabs> |
61 |
| - |
62 |
| - |
63 |
| -<TabItem value="Python" label="Python" default> |
| 68 | +### C++ |
| 69 | +```cpp |
| 70 | +class Node { |
| 71 | +public: |
| 72 | + int val; |
| 73 | + Node* next; |
| 74 | + Node* random; |
| 75 | + |
| 76 | + Node(int _val) { |
| 77 | + val = _val; |
| 78 | + next = NULL; |
| 79 | + random = NULL; |
| 80 | + } |
| 81 | +}; |
| 82 | + |
| 83 | +class Solution { |
| 84 | +public: |
| 85 | + Node* copyRandomList(Node* head) { |
| 86 | + if (!head) return nullptr; |
| 87 | + |
| 88 | + // Step 1: Create a new node for each original node and insert it next to the original node. |
| 89 | + Node* curr = head; |
| 90 | + while (curr) { |
| 91 | + Node* newNode = new Node(curr->val); |
| 92 | + newNode->next = curr->next; |
| 93 | + curr->next = newNode; |
| 94 | + curr = newNode->next; |
| 95 | + } |
64 | 96 |
|
65 |
| - <SolutionAuthor name="sivaprasath2004"/> |
| 97 | + // Step 2: Assign random pointers for the new nodes. |
| 98 | + curr = head; |
| 99 | + while (curr) { |
| 100 | + if (curr->random) { |
| 101 | + curr->next->random = curr->random->next; |
| 102 | + } |
| 103 | + curr = curr->next->next; |
| 104 | + } |
66 | 105 |
|
67 |
| - ```python |
| 106 | + // Step 3: Restore the original list and extract the copied list. |
| 107 | + curr = head; |
| 108 | + Node* copiedHead = head->next; |
| 109 | + Node* copiedCurr = copiedHead; |
| 110 | + while (curr) { |
| 111 | + curr->next = curr->next->next; |
| 112 | + if (copiedCurr->next) { |
| 113 | + copiedCurr->next = copiedCurr->next->next; |
| 114 | + } |
| 115 | + curr = curr->next; |
| 116 | + copiedCurr = copiedCurr->next; |
| 117 | + } |
68 | 118 |
|
69 |
| -class Node: |
70 |
| - def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None): |
71 |
| - self.val = x |
72 |
| - self.next = next |
73 |
| - self.random = random |
| 119 | + return copiedHead; |
| 120 | + } |
| 121 | +}; |
| 122 | +``` |
74 | 123 |
|
75 |
| -def copyRandomList(head: 'Node') -> 'Node': |
76 |
| - if not head: |
77 |
| - return None |
78 |
| - |
79 |
| - current = head |
80 |
| - while current: |
81 |
| - new_node = Node(current.val, current.next, None) |
82 |
| - current.next = new_node |
83 |
| - current = new_node.next |
84 |
| - |
85 |
| - current = head |
86 |
| - while current: |
87 |
| - if current.random: |
88 |
| - current.next.random = current.random.next |
89 |
| - current = current.next.next |
90 |
| - |
91 |
| - original = head |
92 |
| - copy = head.next |
93 |
| - copy_head = copy |
94 |
| - |
95 |
| - while original: |
96 |
| - original.next = original.next.next |
97 |
| - if copy.next: |
98 |
| - copy.next = copy.next.next |
99 |
| - original = original.next |
100 |
| - copy = copy.next |
101 |
| - |
102 |
| - return copy_head |
103 |
| - |
104 |
| - ``` |
105 |
| - </TabItem> |
106 |
| - |
107 |
| - <TabItem value="Js" label="JavaScript" default> |
108 |
| - |
109 |
| - <SolutionAuthor name="sivaprasath2004"/> |
110 |
| - |
111 |
| - ```JS |
| 124 | +### Java |
| 125 | +```java |
112 | 126 | class Node {
|
113 |
| - constructor(val, next = null, random = null) { |
| 127 | + int val; |
| 128 | + Node next; |
| 129 | + Node random; |
| 130 | + |
| 131 | + public Node(int val) { |
114 | 132 | this.val = val;
|
115 |
| - this.next = next; |
116 |
| - this.random = random; |
| 133 | + this.next = null; |
| 134 | + this.random = null; |
117 | 135 | }
|
118 | 136 | }
|
119 | 137 |
|
120 |
| -function copyRandomList(head) { |
121 |
| - if (!head) return null; |
122 |
| - |
123 |
| - let current = head; |
124 |
| - while (current) { |
125 |
| - const newNode = new Node(current.val); |
126 |
| - newNode.next = current.next; |
127 |
| - current.next = newNode; |
128 |
| - current = newNode.next; |
129 |
| - } |
130 |
| - |
131 |
| - current = head; |
132 |
| - while (current) { |
133 |
| - if (current.random) { |
134 |
| - current.next.random = current.random.next; |
| 138 | +class Solution { |
| 139 | + public Node copyRandomList(Node head) { |
| 140 | + if (head == null) return null; |
| 141 | + |
| 142 | + // Step 1: Create a new node for each original node and insert it next to the original node. |
| 143 | + Node curr = head; |
| 144 | + while (curr != null) { |
| 145 | + Node newNode = new Node(curr.val); |
| 146 | + newNode.next = curr.next; |
| 147 | + curr.next = newNode; |
| 148 | + curr = newNode.next; |
135 | 149 | }
|
136 |
| - current = current.next.next; |
137 |
| - } |
138 |
| - current = head; |
139 |
| - const newHead = head.next; |
140 |
| - let copyCurrent = newHead; |
141 |
| - |
142 |
| - while (current) { |
143 |
| - current.next = current.next.next; |
144 |
| - if (copyCurrent.next) { |
145 |
| - copyCurrent.next = copyCurrent.next.next; |
| 150 | + |
| 151 | + // Step 2: Assign random pointers for the new nodes. |
| 152 | + curr = head; |
| 153 | + while (curr != null) { |
| 154 | + if (curr.random != null) { |
| 155 | + curr.next.random = curr.random.next; |
| 156 | + } |
| 157 | + curr = curr.next.next; |
146 | 158 | }
|
147 |
| - current = current.next; |
148 |
| - copyCurrent = copyCurrent.next; |
149 |
| - } |
150 | 159 |
|
151 |
| - return newHead; |
152 |
| -} |
| 160 | + // Step 3: Restore the original list and extract the copied list. |
| 161 | + curr = head; |
| 162 | + Node copiedHead = head.next; |
| 163 | + Node copiedCurr = copiedHead; |
| 164 | + while (curr != null) { |
| 165 | + curr.next = curr.next.next; |
| 166 | + if (copiedCurr.next != null) { |
| 167 | + copiedCurr.next = copiedCurr.next.next; |
| 168 | + } |
| 169 | + curr = curr.next; |
| 170 | + copiedCurr = copiedCurr.next; |
| 171 | + } |
153 | 172 |
|
| 173 | + return copiedHead; |
| 174 | + } |
| 175 | +} |
154 | 176 | ```
|
155 |
| - </TabItem> |
156 |
| - |
157 |
| - </Tabs> |
158 |
| - |
159 | 177 |
|
160 |
| -### Output |
| 178 | +### Python |
| 179 | +```python |
| 180 | +class Node: |
| 181 | + def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None): |
| 182 | + self.val = x |
| 183 | + self.next = next |
| 184 | + self.random = random |
161 | 185 |
|
162 |
| - |
| 186 | +class Solution: |
| 187 | + def copyRandomList(self, head: 'Node') -> 'Node': |
| 188 | + if not head: |
| 189 | + return None |
| 190 | + |
| 191 | + # Step 1: Create a new node for each original node and insert it next to the original node. |
| 192 | + curr = head |
| 193 | + while curr: |
| 194 | + newNode = Node(curr.val) |
| 195 | + newNode.next = curr.next |
| 196 | + curr.next = newNode |
| 197 | + curr = newNode.next |
| 198 | + |
| 199 | + # Step 2: Assign random pointers for the new nodes. |
| 200 | + curr = head |
| 201 | + while curr: |
| 202 | + if curr.random: |
| 203 | + curr.next.random = curr.random.next |
| 204 | + curr = curr.next.next |
| 205 | + |
| 206 | + # Step 3: Restore the original list and extract the copied list. |
| 207 | + curr = head |
| 208 | + copiedHead = head.next |
| 209 | + copiedCurr = copiedHead |
| 210 | + while curr: |
| 211 | + curr.next = curr.next.next |
| 212 | + if copiedCurr.next: |
| 213 | + copiedCurr.next = copiedCurr.next.next |
| 214 | + curr = curr.next |
| 215 | + copiedCurr = copiedCurr.next |
| 216 | + |
| 217 | + return copiedHead |
| 218 | +``` |
163 | 219 |
|
164 | 220 | ### Complexity
|
165 | 221 |
|
166 |
| -- **Time Complexity:** O(n), where `n` is the number of nodes in the linked list. The algorithm iterates through the list three times: once for interweaving nodes, once for setting random pointers, and once for separating the lists. |
| 222 | +- **Time Complexity:** $O(n)$ - Each of the three steps involves a single pass through the list. |
| 223 | +- **Space Complexity:** $O(1)$ - The space complexity is constant as we are not using any additional data structures for storage. |
167 | 224 |
|
168 |
| -- **Space Complexity:** O(1), since the algorithm uses a constant amount of extra space beyond the input list itself (e.g., pointers for traversal and temporary variables). |
| 225 | +### Summary |
169 | 226 |
|
| 227 | +This approach efficiently creates a deep copy of a linked list with random pointers by leveraging the existing structure of the list and ensuring that each node and its clone are linked adjacently. |
0 commit comments