zl程序教程

您现在的位置是:首页 >  其他

当前栏目

【LeetCode】将N叉树编码为二叉树(使用深度优先递归)

LeetCode编码二叉树递归 深度 优先 使用
2023-09-27 14:19:52 时间

431. 将 N 叉树编码为二叉树 - 力扣(LeetCode)

一、题目

设计一个算法,可以将 N 叉树编码为二叉树,并能将该二叉树解码为原 N 叉树。 一个 N 叉树是指每个节点都有不超过 N 个孩子节点的有根树。 类似地,一个二叉树是指每个节点都有不超过 2 个孩子节点的有根树。 你的编码 / 解码的算法的实现没有限制,你只需要保证一个 N 叉树可以编码为二叉树且该二叉树可以解码回原始 N 叉树即可。

例如,你可以将下面的 3-叉 树以该种方式编码:

注意,上面的方法仅仅是一个例子,可能可行也可能不可行。 你没有必要遵循这种形式转化,你可以自己创造和实现不同的方法。

注意: N 的范围在 [1, 1000] 不要使用类成员 / 全局变量 / 静态变量来存储状态。 你的编码和解码算法应是无状态的。

二、代码

/**
 * 将N叉树的每个节点的所有孩子节点,都转换成二叉树的左子树右边界,即可完成N叉树到二叉树的转换
 */
class Solution {
    // Encodes an n-ary tree to a binary tree.
    // 将N叉树转换为二叉树
    public TreeNode encode(Node root) {
        // 根节点为空,直接返回null
        if (root == null) {
            return null;
        }
        // 将N叉树根节点转换为二叉树节点
        TreeNode head = new TreeNode(root.val);
        // 将N叉树所有的孩子节点都添加到二叉树的左子树的右边界上,通过递归去实现
        head.left = en(root.children);
        return head;
    }

    // 是一个深度优先递归,先递归到最底,在向上返回时再进行每一层递归栈的操作
    private TreeNode en(List<Node> children) {
        // 创建二叉树节点,表示左子树的根节点
        TreeNode head = null;
        // 遍历时的当前节点
        TreeNode cur = null;
        // 遍历N叉树节点所有的孩子节点,将所有的孩子都往右边界上挂
        for (Node child : children) {
            // 将N叉树节点转换为孩子节点
            TreeNode tNode = new TreeNode(child.val);
            // 如果左子树根节点为空,说明这是第一轮循环,还没有任何N叉树孩子节点添加到左子树上,这里就初始化左子树根节点
            if (head == null) {
                // 将当前N叉树孩子节点设置为二叉树左子树根节点
                head = tNode;
            } else {
                // 这里cur是上一次循环到的节点,我们要把所有的子孩子都加到有边界,所以将本次循环到的子孩子tNode追加到上一次循环到的节点的右子节点处
                cur.right = tNode;
            }
            // cur指向本次循环到的孩子节点
            cur = tNode;
            // 递归去继续转换本次遍历到的节点的孩子,这里就是深度优先递归,先递归到最底,然后在向上返回的过程中处理余下的孩子节点
            cur.left = en(child.children);
        }
        return head;
    }

    // Decodes your binary tree to an n-ary tree.
    // 将二叉树转换为N叉树
    public Node decode(TreeNode root) {
        if (root == null) {
            return null;
        }
        // 调用递归函数,将二叉树转换为N叉树
        return new Node(root.val, de(root.left));
    }

    // 是一个深度优先递归
    public List<Node> de(TreeNode root) {
        // 创建存放孩子节点的List<Node>
        List<Node> children = new ArrayList<>();
        // 将每一个节点的左子树上所有右边界的节点全部添加到List中,当遍历到null则说明已经将所有的孩子节点添加进List了
        while (root != null) {
            // 创建N叉树节点,并且调用递归函数去转换本次循环到的节点的左子树
            Node cur = new Node(root.val, de(root.left));
            // 将N叉树节点添加到List中
            children.add(cur);
            // 继续向右边界节点遍历
            root = root.right;
        }
        // 返回本层节点的List
        return children;
    }
}

三、解题思路

其实这道题就是N叉树如何通过二叉树来序列化、并完成反序列化的问题,本质就是实现将N叉树转换为二叉树,二叉树转换为N叉树的过程

转换原则:多叉树任何X所有孩子节点放在X的左树右边界,右树根本不用。