将 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词向量模型
深度学习掀开了机器学习的新篇章,目前深度学习应用于图像和语音已经产生了突破性的研究进展.深度学习一直被人们推崇为一种类似于人脑结构的人工智能算法,那为什么深度学习在语义分析领域仍然没有实质性的进展呢? ...
随机推荐
- ElementUI嵌套页面及关联增删查改实现
@ 目录 前言 一.ElementUI如何在原有页面添加另外一个页面并实现关联增删查改? 二.实现步骤 1.ElementUI代码 2.思路:很简单 1.1 首先通过el-row.el-col.el- ...
- 如何用WebGPU流畅渲染千万级2D物体:基于光追管线
大家好~我们已经实现了百万级2D物体的流畅渲染,不过是基于计算管线实现的.本文在它的基础上,改为基于光追管线实现,主要进行了CPU和GPU端内存的优化,成功地将渲染的2D物体数量由4百万提高到了2千万 ...
- CF859E 题解
分析 我们不妨把这些座位看作是一张图中的节点,把每个人的诉求作为一条边(由[原座位]指向[想去的座位]) 比如,对于样例#1,我们就可以得到这样一张图: 显然,我们有可能会得到多个连通图(比如上面这张 ...
- C++11实现可变参数泛型抽象工厂
- Luogu1993 小K的农场 (差分约束)
\(if \ a - b <= c, AddEdge(b, a, c)\) Be careful, MLE is not good. #include <cstdio> #inclu ...
- Luogu2801 教主的魔法 (分块)
与hzw的分块2类似,放vector排序 #include <iostream> #include <cstdio> #include <cstring> #inc ...
- java学习第七天xml.day18
反射 在java中,反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力. 获取字节码的方式: 使用反射获取构造器 : 内省
- Python小白自学笔记:英语不好,变量怎么命名
变量其实很简单,不过在使用过程中会遇到一些棘手的问题. 比如一个变量我之前已经用过了,现在我要定义一个类似的变量,该怎么办? 还有,很多小伙伴其实知道变量应该遵守什么规范,应该代表什么数据,但是大学英 ...
- 没写完。【java】IDEA-调教界面、设置语言、插件的使用
步骤: 1.官方网站:https://www.jetbrains.com/idea/ (zip)版本:https://download.jetbrains.com.cn/idea/ideaIC-202 ...
- Qt 创建按钮动画
1 封装自定义按钮 myPushBttton 2 构造函数 (默认图片,按下后显示图片) 3 测试开始按钮 4 开始制作特效 5 zoom1 向下弹跳 6 zoom2 向上弹跳 代码如下 main.h ...