• 将 N 叉树编码为二叉树


    将 N 叉树编码为二叉树

    作者:Grey

    原文地址:

    博客园:将 N 叉树编码为二叉树

    CSDN:将 N 叉树编码为二叉树

    题目描述#

    将一棵n叉树编码为一棵二叉树,并对二叉树进行解码,得到原始的n叉树。 n叉树是一棵有根树,其中每个节点的子树不超过n个。 类似地,二叉树是一棵有根树,其中每个节点的子树不超过2个。 编码/解码算法的工作方式不受限制。 您只需要确保一个n叉树可以被编码为一个二叉树,并且这个二叉树可以被解码为原始的n叉树结构。

    题目链接:LintCode 1530 · Encode N-ary Tree to Binary Tree

    一棵 N 叉树的示例如下

    image

    二叉树的数据结构如下

    class TreeNode {
        public int val;
        public TreeNode left, right;
    
        public TreeNode(int val) {
            this.val = val;
            this.left = this.right = null;
        }
    }
    

    N 叉树的数据结构如下

    class UndirectedGraphNode {
         int label;
         List neighbors;
         UndirectedGraphNode(int x) {
             label = x;
             neighbors = new ArrayList();
         }
    } 
    

    每个节点有属于自己的 label 值,也有若干个孩子节点,即List neighbors

    我们需要实现如下两个方法

    // N 叉树编码成 二叉树
    TreeNode encode(UndirectedGraphNode root)
    // 二叉树编码成 N 叉树
    UndirectedGraphNode decode(TreeNode root)
    

    主要思路#

    N 叉树编码成二叉树的方法是将 N 叉树中每个节点的子节点转换成自己左树的右边界或者右树的左边界,示例图如下

    image

    二叉树编码成 N 叉树的方法就是把每个节点的左树右边界存到一个 List 里面,作为这个节点的子节点列表即可,就是上述示例图的逆过程。

    N 叉树编码成二叉树的过程就是一个深度优先遍历,首先

    TreeNode head = new TreeNode(root.label);
    

    表示二叉树的根节点就是 N 叉树的根节点,

    然后将根节点的孩子节点,调用递归,进行深度优先遍历,代码如下

    // 将某个节点的孩子节点挂在其右树的左边界上
    // 将 N 叉树的根节点的孩子节点做深度优先遍历
    // 并将其挂在根节点的右树上
    head.right = en(root.neighbors);
    
    // 深度优先遍历
    private TreeNode en(List neighbors) {
            TreeNode c = null;
            TreeNode head = null;
            for (UndirectedGraphNode neighbor : neighbors) {
                TreeNode node = new TreeNode(neighbor.label);
                if (head == null) {
                    // 头节点为空,建出来
                    head = node;
                } else {
                    // 否则挂在当前节点的右树的左边界上
                    c.left = node;
                }
                c = node;
                c.right = en(neighbor.neighbors);
            }
            return head;
    }
    

    将二叉树转换成 N 叉树的逻辑如下:

    首先

    UndirectedGraphNode node = new UndirectedGraphNode(root.val);
    

    表示:N 叉树的根节点也是二叉树的根节点。

    接着调用递归,将二叉树的右树构造出 N 叉树当前节点的孩子节点。

    // 将二叉树的右树构造出 N 叉树当前节点的孩子节点
    node.neighbors = de(root.right);
    
    public ArrayList de(TreeNode root) {
        ArrayList children = new ArrayList<>();
        while (root != null) {
            UndirectedGraphNode cur = new UndirectedGraphNode(root.val);
            cur.neighbors = de(root.right);
            children.add(cur);
            root = root.left;
        }
        return children;
    }
    

    其中 while 循环中就是不断的把当前节点的左树右边界加入到一个 List 中,最后返回。

    完整代码如下

    public class Solution {
        public UndirectedGraphNode decode(TreeNode root) {
            if (root == null) {
                return null;
            }
            UndirectedGraphNode node = new UndirectedGraphNode(root.val);
            node.neighbors = de(root.right);
            return node;
        }
    
        public ArrayList de(TreeNode root) {
            ArrayList children = new ArrayList<>();
            while (root != null) {
                UndirectedGraphNode cur = new UndirectedGraphNode(root.val);
                cur.neighbors = de(root.right);
                children.add(cur);
                root = root.left;
            }
            return children;
        }
    
        // 每个子节点转换成自己左树的右边界或者右树的左边界 + 深度优先遍历
        // 编码
        public TreeNode encode(UndirectedGraphNode root) {
            if (root == null) {
                return null;
            }
            TreeNode head = new TreeNode(root.label);
            // 右树的左边界
            head.right = en(root.neighbors);
            return head;
        }
    
        private TreeNode en(List neighbors) {
            TreeNode c = null;
            TreeNode head = null;
            for (UndirectedGraphNode neighbor : neighbors) {
                TreeNode node = new TreeNode(neighbor.label);
                if (head == null) {
                    // 头节点为空,建出来
                    head = node;
                } else {
                    // 否则挂在当前节点的右树的左边界上
                    c.left = node;
                }
                c = node;
                c.right = en(neighbor.neighbors);
            }
            return head;
        }
    }
    

    本文涉及到的所有图例见:二叉树与N叉树的互相转换

    更多#

    算法和数据结构笔记

  • 相关阅读:
    MFC创建一个接收消息但不显示的窗口
    Python R用法:深度探索与实用技巧
    基于Java+SpringBoot+Vue前后端分离高校教师科研管理系统设计和实现
    计算机网络——第六章笔记(2)
    北极星指标|专家建议如何有效制订NSM以驱动增长
    Dubbo-RPC核心接口介绍
    Keepalived手动编译安装以及Nginx网关服务器冗余策略
    百题千解计划【CSDN每日一练】“编码”:编码工作常被运用于密文或压缩传输。这里我们用一种最简单的编码方式进行编码,把一些有规律的单词编成数字...实现方式:Python、C++、Java、JS...
    vins-course运行
    Maven安装与配置
  • 原文地址:https://www.cnblogs.com/greyzeng/p/16758370.html