0% completed
Problem Statement
You are given a linked list where each node contains an additional random pointer. This pointer could point to any node in the list or be null
.
Create a deep copy of this linked list. The deep copy should have n
new nodes, where each new node's value matches the value of its corresponding node in the original list. Additionally, both the next
and random
pointers of the new nodes should point to the new nodes in the copied list.
The pointers in the copied list should maintain the same structure as the original list. None of the pointers in the new list should reference any node in the original list.
For instance, if in the original list, node X has a random pointer to node Y (X.random -> Y
), then in the copied list, the corresponding nodes x and y should have a random pointer such that x.random -> y
.
The linked list is represented in the input/output as a list of n
nodes. Each node is represented as a pair of [val, randomIndex]
where:
val
: It is an integer representing Node.valrandomIndex:
The index of the node (range from0
ton-1
) that the random pointer points to, or null if it does not point to any node.
Given a head
of the linked list, return the head of the newly copied linked list.
Examples
Example 1:
- Input: head =
[[3, 1], [4, null], [5, 0], [7, 2]]
- Output:
[[3, 1], [4, null], [5, 0], [7, 2]]
- Explanation: The original list is cloned and returned.
Example 2:
- Input: head =
[[1, 2], [2, 0], [3, 1]]
- Expected Output:
[[1, 2], [2, 0], [3, 1]]
- Explanation: The original list is cloned and returned.
Example 3:
- Input: head =
[[8, 2], [9, null], [7, 1]]
- Output:
[[8, 2], [9, null], [7, 1]]
- Explanation: The original list is cloned and returned.
Constraints:
- 0 <= n <= 1000
- -10<sup>4</sup> <= Node.val <= 10<sup>4</sup>
Node.random
is null or is pointing to some node in the linked list.
Solution
To solve this problem, we make three passes over the original linked list to create a deep copy that maintains the same next
and random
pointer structure as the original list. In the first pass, we insert a copy of each node right next to the original node. This helps us easily link the next
pointers of the copied nodes. During the second pass, we set up the random
pointers for the copied nodes using the established relationship between the original nodes and their copies. Finally, in the third pass, we separate the original and copied nodes, restoring the original list and forming the deep-copied list.
This approach is efficient because it only traverses the list three times, maintaining a linear time complexity of O(n). The algorithm avoids using extra space by cleverly utilizing the linked list structure to temporarily store the copied nodes next to their originals. This enables us to keep track of the next
and random
pointers without additional data structures, making the solution space-efficient with O(1) extra space.
Step-by-Step Algorithm
-
Check for Empty List:
- If the input
head
isnull
, returnnull
. This handles the edge case where the input list is empty.
- If the input
-
First Pass: Create and Insert Copied Nodes:
- Initialize a pointer
current
to thehead
of the original list. - Traverse the list while
current
is notnull
:- For each node (
current
), create a new nodecopy
with the same value (current.val
). - Set the
next
pointer ofcopy
tocurrent.next
. - Insert
copy
right aftercurrent
by settingcurrent.next
tocopy
. - Move
current
tocopy.next
(i.e., the next original node).
- For each node (
- Initialize a pointer
-
Second Pass: Set Random Pointers for Copied Nodes:
- Reinitialize
current
to thehead
of the original list. - Traverse the list again while
current
is notnull
:- If
current.random
is notnull
, set therandom
pointer ofcurrent.next
(the copied node) tocurrent.random.next
(the copy of the nodecurrent.random
points to). - Move
current
tocurrent.next.next
(i.e., the next original node).
- If
- Reinitialize
-
Third Pass: Separate the Original and Copied Lists:
- Reinitialize
current
to thehead
of the original list. - Initialize
copiedHead
tohead.next
(the head of the copied list). - Use a pointer
copy
to iterate over the copied list, initially set tocopiedHead
. - Traverse the list while
current
is notnull
:- Set
current.next
tocurrent.next.next
to restore the original list. - If
copy.next
is notnull
, setcopy.next
tocopy.next.next
to form the copied list. This steps removes the node of the original list. - Move both
current
andcopy
to their respectivenext
nodes.
- Set
- Reinitialize
-
Return the Head of the Copied List:
- Return
copiedHead
, which points to the head of the deep-copied linked list.
- Return
Algorithm Walkthrough
Let's walk through the algorithm using the input head = [[3, 1], [4, null], [5, 0], [7, 2]]
.
- Input Linked List:
- Node 1: Value
3
, Random Pointer -> Node at index1
(Node with value4
) - Node 2: Value
4
, Random Pointer ->null
- Node 3: Value
5
, Random Pointer -> Node at index0
(Node with value3
) - Node 4: Value
7
, Random Pointer -> Node at index2
(Node with value5
)
- Node 1: Value
First Pass: Create and Insert Copied Nodes
-
Start with
current
at Node 1 (Value3
):- Create
Node 1'
(Value3
). - Insert
Node 1'
after Node 1:- The list becomes:
3 -> 3' -> 4 -> 5 -> 7
.
- The list becomes:
- Move
current
to Node 2 (Value4
).
- Create
-
At Node 2 (Value
4
):- Create
Node 2'
(Value4
). - Insert
Node 2'
after Node 2:- The list becomes:
3 -> 3' -> 4 -> 4' -> 5 -> 7
.
- The list becomes:
- Move
current
to Node 3 (Value5
).
- Create
-
At Node 3 (Value
5
):- Create
Node 3'
(Value5
). - Insert
Node 3'
after Node 3:- The list becomes:
3 -> 3' -> 4 -> 4' -> 5 -> 5' -> 7
.
- The list becomes:
- Move
current
to Node 4 (Value7
).
- Create
-
At Node 4 (Value
7
):- Create
Node 4'
(Value7
). - Insert
Node 4'
after Node 4:- The list becomes:
3 -> 3' -> 4 -> 4' -> 5 -> 5' -> 7 -> 7'
.
- The list becomes:
- Move
current
tonull
, ending the first pass.
- Create
Second Pass: Set Random Pointers for Copied Nodes
-
Start with
current
at Node 1 (Value3
):current.random
points to Node 2 (Value4
).- Set
Node 1'.random
toNode 2'.random
:Node 3'.random
is now correctly set to Node 2'.
- Move
current
to Node 2 (Value4
).
-
At Node 2 (Value
4
):current.random
isnull
.Node 2'.random
remainsnull
.- Move
current
to Node 3 (Value5
).
-
At Node 3 (Value
5
):current.random
points to Node 1 (Value3
).- Set
Node 3'.random
toNode 1'.random
:Node 3'.random
is now correctly set to Node 1'.
- Move
current
to Node 4 (Value7
).
-
At Node 4 (Value
7
):current.random
points to Node 3 (Value5
).- Set
Node 4'.random
toNode 3'.random
:Node 4'.random
is now correctly set to Node 3'.
- Move
current
tonull
, ending the second pass.
Third Pass: Separate the Original and Copied Lists
-
Start with
current
at Node 1 (Value3
),copiedHead
at Node 1' (Value3
), andcopy
at Node 1'.- Set
current.next
to Node 2 (restoring the original list). - Set
copy.next
to Node 2'. - Move
current
to Node 2 andcopy
to Node 2'.
- Set
-
At Node 2 (Value
4
):- Set
current.next
to Node 3 (restoring the original list). - Set
copy.next
to Node 3'. - Move
current
to Node 3 andcopy
to Node 3'.
- Set
-
At Node 3 (Value
5
):- Set
current.next
to Node 4 (restoring the original list). - Set
copy.next
to Node 4'. - Move
current
to Node 4 andcopy
to Node 4'.
- Set
-
At Node 4 (Value
7
):- Set
current.next
tonull
(restoring the original list). - Set
copy.next
tonull
. - Move
current
tonull
andcopy
tonull
, ending the third pass.
- Set
Final Output
- Copied List:
3' -> 4' -> 5' -> 7'
, with correctnext
andrandom
pointers.
- Original List remains unchanged:
3 -> 4 -> 5 -> 7
.
Code
Complexity Analysis
Time Complexity
The time complexity of the solution is O(n), where n
is the number of nodes in the linked list. This is because we perform three passes over the list:
- The first pass creates a copy of each node and inserts it immediately after the original node, taking O(n) time.
- The second pass sets the
random
pointers for the copied nodes, which also takes O(n) time. - The third pass separates the original and copied lists, which again requires O(n) time. Thus, the total time complexity is O(n + n + n) = O(n).
Space Complexity
The space complexity is O(1) (excluding the space required for the output). This is because we do not use any extra space proportional to the input size; we only manipulate the existing nodes to achieve the deep copy.
.....
.....
.....
Table of Contents
Contents are not accessible
Contents are not accessible
Contents are not accessible
Contents are not accessible
Contents are not accessible