This problem requires creating a deep copy of a binary tree where each node has an additional random
pointer that can point to any node in the tree or be null
. The solution uses Depth-First Search (DFS) and a hash map (dictionary in Python) to efficiently track nodes and their corresponding copies.
The core idea is to perform a recursive DFS traversal of the tree. For each node encountered:
Check the hash map: If the node already exists in the hash map (meaning its copy has already been created), return the copied node.
Create a new node: Otherwise, create a new node (NodeCopy
) with the same value as the original node.
Store in hash map: Add the original node and its newly created copy to the hash map to avoid redundant work.
Recursively copy children and random pointer: Recursively call the dfs
function on the left and right children of the current node and on the node pointed to by the random
pointer. This ensures a deep copy where all connections are replicated.
Return the copied node: Return the newly created copied node.
Time Complexity: O(N), where N is the number of nodes in the tree. This is because each node is visited and processed exactly once during the DFS traversal.
Space Complexity: O(N) in the worst case. This is due to the space used by the hash map to store the mapping between original nodes and their copied counterparts. In the worst-case scenario (a skewed tree), the recursion depth can also be O(N).
class Solution:
def copyRandomBinaryTree(self, root: 'Optional[Node]') -> 'Optional[NodeCopy]':
def dfs(root):
if root is None:
return None
if root in mp:
return mp[root] # If already copied, return the copy
copy = NodeCopy(root.val)
mp[root] = copy # Store the mapping
copy.left = dfs(root.left)
copy.right = dfs(root.right)
copy.random = dfs(root.random)
return copy
mp = {} # Hash map to store node mappings
return dfs(root)
The code in other languages (Java, C++, Go) follows the same logic, utilizing their respective hash map implementations (HashMap, unordered_map, map). The key difference lies primarily in the syntax and data structures used, but the algorithmic core remains identical. The use of a hash map ensures that we avoid repeatedly copying the same nodes, leading to the optimal O(N) time complexity.