将 N 叉树编码为二叉树
将 N 叉树编码为二叉树
作者:Grey
原文地址:
题目描述
将一棵n叉树编码为一棵二叉树,并对二叉树进行解码,得到原始的n叉树。 n叉树是一棵有根树,其中每个节点的子树不超过n个。 类似地,二叉树是一棵有根树,其中每个节点的子树不超过2个。 编码/解码算法的工作方式不受限制。 您只需要确保一个n叉树可以被编码为一个二叉树,并且这个二叉树可以被解码为原始的n叉树结构。
题目链接:LintCode 1530 · Encode N-ary Tree to Binary Tree
一棵 N 叉树的示例如下

二叉树的数据结构如下
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<UndirectedGraphNode> neighbors;
UndirectedGraphNode(int x) {
label = x;
neighbors = new ArrayList<UndirectedGraphNode>();
}
}
每个节点有属于自己的 label 值,也有若干个孩子节点,即List<UndirectedGraphNode> neighbors。
我们需要实现如下两个方法
// N 叉树编码成 二叉树
TreeNode encode(UndirectedGraphNode root)
// 二叉树编码成 N 叉树
UndirectedGraphNode decode(TreeNode root)
主要思路
N 叉树编码成二叉树的方法是将 N 叉树中每个节点的子节点转换成自己左树的右边界或者右树的左边界,示例图如下

二叉树编码成 N 叉树的方法就是把每个节点的左树右边界存到一个 List 里面,作为这个节点的子节点列表即可,就是上述示例图的逆过程。
N 叉树编码成二叉树的过程就是一个深度优先遍历,首先
TreeNode head = new TreeNode(root.label);
表示二叉树的根节点就是 N 叉树的根节点,
然后将根节点的孩子节点,调用递归,进行深度优先遍历,代码如下
// 将某个节点的孩子节点挂在其右树的左边界上
// 将 N 叉树的根节点的孩子节点做深度优先遍历
// 并将其挂在根节点的右树上
head.right = en(root.neighbors);
// 深度优先遍历
private TreeNode en(List<UndirectedGraphNode> 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<UndirectedGraphNode> de(TreeNode root) {
ArrayList<UndirectedGraphNode> 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<UndirectedGraphNode> de(TreeNode root) {
ArrayList<UndirectedGraphNode> 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<UndirectedGraphNode> 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叉树的互相转换
更多
将 N 叉树编码为二叉树的更多相关文章
- [LeetCode] Encode N-ary Tree to Binary Tree 将N叉树编码为二叉树
Design an algorithm to encode an N-ary tree into a binary tree and decode the binary tree to get the ...
- 剑指offer-面试题27-二叉树的镜像-二叉树
/* 题目:输入一个二叉树,输出该函数的镜像. */ /* 思路: 基础条件:树为空,或只有一个节点. 其它:递归交换二叉树的左右子树. */ void Mirror(TreeNode *pRoot) ...
- leetcode难题
4 寻找两个有序数组的中位数 35.9% 困难 10 正则表达式匹配 24.6% 困难 23 合并K个排序链表 47.4% 困难 25 K ...
- [数据结构与算法]哈夫曼(Huffman)树与哈夫曼编码
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- POJ 1240 Pre-Post-erous! && East Central North America 2002 (由前序后序遍历序列推出M叉树的种类)
题目链接 问题描述 : We are all familiar with pre-order, in-order and post-order traversals of binary trees. ...
- POJ 1240 Pre-Post-erous! && East Central North America 2002 (由前序后序遍历序列推出M叉树的种类)
题目链接:http://poj.org/problem?id=1240 本文链接:http://www.cnblogs.com/Ash-ly/p/5482520.html 题意: 通过一棵二叉树的中序 ...
- C#数据结构-线索化二叉树
为什么线索化二叉树? 对于二叉树的遍历,我们知道每个节点的前驱与后继,但是这是建立在遍历的基础上,否则我们只知道后续的左右子树.现在我们充分利用二叉树左右子树的空节点,分别指向当前节点的前驱.后继,便 ...
- leetcode_二叉树篇_python
主要是深度遍历和层序遍历的递归和迭代写法. 另外注意:因为求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中). 所有题目首先考虑root否是空.有的 ...
- [Algorithm & NLP] 文本深度表示模型——word2vec&doc2vec词向量模型
深度学习掀开了机器学习的新篇章,目前深度学习应用于图像和语音已经产生了突破性的研究进展.深度学习一直被人们推崇为一种类似于人脑结构的人工智能算法,那为什么深度学习在语义分析领域仍然没有实质性的进展呢? ...
随机推荐
- DQL条件查询模糊查询和约束概述
模糊查询 -- 查询姓马的有哪些? like SELECT * FROM student where name LIKE '马%'; -- 查询姓名第二个字是化的人 SELECT * FROM stu ...
- 反射概述和反射获取字节码Class对象的三种方式
反射:框架设计的灵魂 框架:半成品软件.可以在框架的基础上进行软件开发,简化变法 反射:将类的各个组成部分封装为其他对象,这就是反射机制 好处: 1.可以在程序运行的过程中操作这些对象. 2.可以解耦 ...
- 国产钡铼分布式IO模块如何与西门子PLC Profinet通讯
1.准备IO模块:耦合器BL200PN.数字量输出模块M2082.数字量输入M1081.模拟量输入模块M3401.模拟量输出M4043. 编辑搜图 请点击输入图片描述(最多18字) 2.BL200P ...
- 跳转语句break、continue、return
1.break 语句 概念: break语句在循环中的作用是终止当前循环,在switch语句中的作用是终止switch. 示例: 输出结果: 2.continue 语句 概念: continue语句 ...
- BMP位图之8位位图(三)
起始结构 typedef struct tagBITMAPFILEHEADER { WORD bfType; //类型名,字符串"BM", DWORD bfSize; //文件大小 ...
- 官宣!DolphinScheduler 毕业成为 Apache 软件基金会顶级项目
全球最大的开源软件基金会 Apache 软件基金会(以下简称 Apache)于北京时间 2021年4月9日在官方渠道宣布Apache DolphinScheduler 毕业成为Apache顶级项目.这 ...
- 成为 Apache 贡献者,从提交第一个简单 PR 开始!
开源之路,PR 走起 ! ---全球最大同性交友社区 1 fork 以下实例以 incubator-dolphinscheduler 海豚调度为例进行操作 从远端仓库* https://github. ...
- 图解OSI七层模型
七层模型,亦称OSI(Open System Interconnection)参考模型,是参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系.它是一个七层的.抽象的模型体 ...
- spring-aop-事务-注解开发-代理
1.spring + mybatis: Aop流程: 提前定义好几个用于Aop的类 前置通知:新建MyBeForeAdvice类 实现 MethodBeforeAdvice,并实现其方法 后置通知:新 ...
- LGV 引理——二维DAG上 n 点对不相交路径方案数
文章目录 引入 简介 定义 引理 证明 例题 释疑 扩展 引入 有这样一个问题: 甲和乙在一张网格图上,初始位置 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1,y_1),(x_ ...