将 N 叉树编码为二叉树

作者:Grey

原文地址:

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

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

题目描述

将一棵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 叉树编码为二叉树的更多相关文章

  1. [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 ...

  2. 剑指offer-面试题27-二叉树的镜像-二叉树

    /* 题目:输入一个二叉树,输出该函数的镜像. */ /* 思路: 基础条件:树为空,或只有一个节点. 其它:递归交换二叉树的左右子树. */ void Mirror(TreeNode *pRoot) ...

  3. leetcode难题

    4 寻找两个有序数组的中位数       35.9% 困难     10 正则表达式匹配       24.6% 困难     23 合并K个排序链表       47.4% 困难     25 K ...

  4. [数据结构与算法]哈夫曼(Huffman)树与哈夫曼编码

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  5. 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. ...

  6. 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 题意: 通过一棵二叉树的中序 ...

  7. C#数据结构-线索化二叉树

    为什么线索化二叉树? 对于二叉树的遍历,我们知道每个节点的前驱与后继,但是这是建立在遍历的基础上,否则我们只知道后续的左右子树.现在我们充分利用二叉树左右子树的空节点,分别指向当前节点的前驱.后继,便 ...

  8. leetcode_二叉树篇_python

    主要是深度遍历和层序遍历的递归和迭代写法. 另外注意:因为求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中). 所有题目首先考虑root否是空.有的 ...

  9. [Algorithm & NLP] 文本深度表示模型——word2vec&doc2vec词向量模型

    深度学习掀开了机器学习的新篇章,目前深度学习应用于图像和语音已经产生了突破性的研究进展.深度学习一直被人们推崇为一种类似于人脑结构的人工智能算法,那为什么深度学习在语义分析领域仍然没有实质性的进展呢? ...

随机推荐

  1. tarjan算法和缩点

    tarjan可以找强连通的分量,但它的作用不只局限于此 缩点,说白了,就是建新图,之后的操作在新图上进行 自己看代码 #include<bits/stdc++.h> using names ...

  2. linux 学习 mysql安装到连接

    在Centos7.6 上安装mysql ps:一般mysql安装后会在/var/log/下面生成一个mysqld.log文件,如果遇到启动不了或者其他问题,基本都可以在这个log文件里面找到错误原因 ...

  3. 膜 社论(egg drop)

    题面 \(n\) 楼 \(m\) 个鸡蛋,从 \(k\) 楼及以上扔下去会碎,不能再测试 . 问至少需要扔几次确定 \(k\) . \(n\le 10^{18}\),\(m\le 64\) . 题解 ...

  4. Vue 模板语法 && 数据绑定

    1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 & ...

  5. 4.5省选模拟solution

    \(4.5\)省选测试\(solution\) 题面可是我精心准备(咕咕咕)了一周写出来的,大家就当看故事吧(那里面的人物确实是存在的,\(E\)就是本人啦,也算是对一段经历的回忆吧,所以这套考试的题 ...

  6. 【原创】Magisk+Shamiko过APP ROOT检测

    本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! Magisk+Shamiko过APP R ...

  7. MySQL主从复制之半同步(semi-sync replication)

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 半同步简介 MASTER节点在执行完客户端提交的事务后不是立刻返回结果给客户端,而是等待至少一个SLAVE节点接收并写到r ...

  8. Point2和Point3类定义

    支持以下图中的运算 类声明: class Point2 { public: Point2(); ~Point2(); Point2(ldouble a); Point2(ldouble a, ldou ...

  9. js仿toDoList(待办事项)练习

    JS的一个小练习 展示成果 话不多说 html骨架 <!DOCTYPE html> <html lang="en"> <head> <me ...

  10. Linux系列之链接

    前言 在类Unix系统中,一个文件有可能被多个名字引用.我们使用链接来实现这一点,链接共有两种类型:硬链接和软链接,本文分别来介绍它们. 硬链接 硬链接也允许指向文件,但与符号链接的方式不同.它们是U ...