题目描述

✅ 1490. 克隆 N 叉树

题意分析

给定一棵 N 叉树,创建一棵结构完全相同的新树:对应节点值一致,每个节点的孩子数量和排列顺序也一致。

这是深拷贝,副本的所有节点及孩子容器都必须独立于原树。只复制根的值、列表或指针都不够;修改任一副本节点不应影响原树。空树的副本仍为空。

解法:深度优先递归克隆

核心思路

[!blue]

定义递归函数返回“当前节点为根的整棵子树的独立副本”。如果当前节点为空,直接返回空;否则先创建一个同值的新节点,并为它建立新的孩子容器。

按原顺序访问每个孩子,递归得到该孩子整棵子树的副本,再将返回的新根加入新容器。不能把原孩子直接加入,因为容器独立并不代表里面的节点也独立。

叶子没有孩子,创建同值新节点后即可完成。假设各个孩子的递归结果已经保留结构与顺序、且没有共享原节点,将它们接到当前新节点后,整棵子树也满足同样条件。这个从叶到根的递归关系保证最终得到完整深拷贝。

输入是树,每个非根节点只有一个父节点,没有环或跨分支共享引用,所以每个原节点只会沿唯一父子路径被复制一次,不需要像克隆图那样建立访问映射。

解题步骤

  1. 当前根为空时返回空。
  2. 创建值与当前根相同的新节点,并初始化新的孩子容器。
  3. 按原孩子列表顺序,递归克隆每棵孩子子树。
  4. 将返回的副本根依次放入新容器,返回当前新节点。

代码实现

class Solution {
    // N 叉树没有随机指针和回边,从根递归复制每个子树即可,不需要哈希表记录已访问节点。
    public Node cloneTree(Node root) {
        if (root == null) {
            return null;
        }

        Node copy = new Node(root.val);

        // 新容器只放克隆后的孩子,不复用原孩子对象。
        copy.children = new ArrayList<>();

        for (Node child : root.children) {
            // 按原孩子顺序递归复制,保持结构和顺序。
            copy.children.add(cloneTree(child));
        }

        return copy;
    }
}
// 返回保持值与孩子顺序的独立子树副本,不共享源节点。
func cloneTree(root *Node) *Node {
    // N 叉树没有随机指针和回边,从根递归复制每个子树即可,不需要哈希表记录已访问节点。
    if root == nil {
        return nil
    }

    // 为当前节点创建独立对象与孩子容器。
    node := &Node{
        Val:      root.Val,
        Children: make([]*Node, 0, len(root.Children)),
    }
    for _, child := range root.Children {
        // 按原孩子顺序递归复制,保持结构和顺序。
        node.Children = append(node.Children, cloneTree(child))
    }

    return node
}

复杂度分析

  • 时间复杂度:$O(n)$,每个节点创建一次,每条父子连接处理一次。
  • 空间复杂度:辅助递归栈为 $O(h)$,其中 $h$ 是树高;深拷贝输出本身需要 $O(n)$。

关键点总结

[!green]

  • 递归返回完整子树副本,父节点只负责把这些新子树按顺序接起来。
  • 节点对象和孩子容器都要新建,所有连接都指向副本。
  • 树的唯一父子路径保证不会重复复制,无需额外映射。

易错点总结

[!yellow]

  • 直接返回原节点只多了一个引用,没有复制数据结构。
  • 创建新列表却放入原孩子,仍会共享整棵孩子子树。
  • 只克隆第一层孩子而不继续递归,会遗漏更深层节点。
  • 随意改变孩子加入顺序,会改变题目要求保留的有序结构。

相似题目

题目 难度 关联与区别
133. 克隆图 中等 图克隆需要映射处理共享与环,本题是纯N叉树时可直接递归复制孩子列表。
1485. 克隆含随机指针的二叉树 中等 原题还含随机指针,需要额外引用映射,本题只有正常父子层级。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2023/28585165
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!