Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1490. Clone N-ary Tree - Leetcode Solution

Code Implementation

"""
# Definition for a Node.
class Node:
    def __init__(self, val = 0, children = None):
        self.val = val
        self.children = children if children is not None else []

class Solution:
    def cloneTree(self, root: 'Node') -> 'Node':
        if root is None:
            return None

        # Create a new node with the same value
        new_root = Node(root.val)
        # Recursively clone all children
        for child in root.children:
            new_root.children.append(self.cloneTree(child))
        return new_root
      
/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
public:
    Node* cloneTree(Node* root) {
        if (!root) return nullptr;
        Node* newRoot = new Node(root->val);
        for (Node* child : root->children) {
            newRoot->children.push_back(cloneTree(child));
        }
        return newRoot;
    }
};
      
/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    public Node cloneTree(Node root) {
        if (root == null) return null;
        Node newRoot = new Node(root.val, new ArrayList<>());
        for (Node child : root.children) {
            newRoot.children.add(cloneTree(child));
        }
        return newRoot;
    }
}
      
/**
 * // Definition for a Node.
 * function Node(val, children) {
 *    this.val = val === undefined ? 0 : val;
 *    this.children = children === undefined ? [] : children;
 * };
 */

/**
 * @param {Node|null} root
 * @return {Node|null}
 */
var cloneTree = function(root) {
    if (root === null) return null;
    let newRoot = new Node(root.val, []);
    for (let child of root.children) {
        newRoot.children.push(cloneTree(child));
    }
    return newRoot;
};
      

Problem Description

Given the root of an N-ary tree, your task is to create a deep copy (clone) of the tree and return the root of the cloned tree. Each node in the tree contains an integer val and a list of child nodes children.

  • You must not reuse any of the original nodes in your cloned tree—every node in the clone must be a new object.
  • There is exactly one valid solution for each input tree.
  • If the input root is null, return null.

The structure and values of the cloned tree should match the original tree exactly.

Thought Process

When asked to clone an N-ary tree, the first instinct might be to simply copy the root and its direct children. However, this only creates a shallow copy, and the child nodes themselves would still reference the original subtrees. Instead, we need a deep copy where every node and its children are independently duplicated.

The recursive nature of trees suggests a recursive approach: for each node, create a new node with the same value, then recursively clone each child. This ensures the entire structure is copied, with no shared references between the original and cloned trees.

If the tree is very large or contains cycles (which is not the case for standard N-ary trees), we might need to handle nodes we've already visited. But for a standard N-ary tree (no cycles), a straightforward recursion is both correct and efficient.

Solution Approach

To clone an N-ary tree, we use a recursive depth-first traversal. Here is the step-by-step approach:

  1. Base Case: If the current node (root) is null, return null.
  2. Create a New Node: Instantiate a new node with the same value as the current node.
  3. Clone Children: For each child in the current node's children list, recursively clone the child and add it to the new node's children list.
  4. Return the New Node: After all children have been cloned and attached, return the new node.

This approach ensures that each node in the original tree is visited exactly once, and a corresponding new node is created in the cloned tree. Since we only traverse downwards and never revisit nodes, we do not need a hash map for visited nodes (as would be necessary for graphs with cycles).

The recursive calls naturally handle all levels of the tree, and the process continues until all leaves are reached.

Example Walkthrough

Consider the following N-ary tree:

  • Root node: 1
  • Children of 1: 3, 2, 4
  • Children of 3: 5, 6
  • Nodes 2, 4, 5, 6 have no children

The recursive cloning proceeds as follows:

  1. Start at node 1. Create a new node with value 1.
  2. For each child of 1:
    • Clone node 3: create new node 3, then recursively clone its children 5 and 6.
    • Clone node 2: create new node 2. Since it has no children, move on.
    • Clone node 4: create new node 4. Since it has no children, move on.
  3. Attach the cloned children to the cloned 1 node.
  4. The process continues recursively for all nodes, resulting in a completely new tree with the same structure and values.

At each step, a new node is created, and its children are filled by recursive calls. No original nodes are referenced in the clone.

Time and Space Complexity

  • Brute-force approach: A naive shallow copy would only duplicate the root and its immediate children, not the entire tree. This would be O(1) for the root but incorrect for the problem.
  • Optimized recursive approach: Each node is visited exactly once, and for each node, we do O(1) work plus recursively process all its children. Thus, the time complexity is O(N), where N is the total number of nodes in the tree.
  • Space complexity: The space used is O(N) for the cloned tree itself. Additionally, the recursion stack will require up to O(H) space, where H is the height of the tree. In the worst case (skewed tree), this is O(N).

Summary

Cloning an N-ary tree is a classic example of recursive traversal. By visiting each node, creating a new node, and recursively cloning all children, we ensure a true deep copy. The solution is elegant because it mirrors the structure of the tree itself, is easy to reason about, and runs efficiently in linear time and space. No extra data structures are needed beyond the recursion stack, making this both simple and robust.