题目要求:给出二叉树的后序遍历序列和中序遍历序列,输出二叉树的层次遍历序列。

传送门

Sample Input

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

Sample Output

4 1 6 3 5 7 2

解题思路

首先,我们在数据结构课程中学过下面的结论:

  • 后序遍历: 左 右 根
  • 中序遍历: 左 根 右

显然,后序序列中的最后一个元素总是某个子树的根,叶子节点也算是一个子树 (可能你觉得这是一句废话)。

此外, 只要确定根,那么可以在中序的某一片段序列中 “分离” 出左右子树。

下面我们来分析一下 Sample ,解析如何从如上2个结论唯一确定一颗二叉树。

在后序序列中:

2 3 1 5 7 6 4

4 毫无疑问是整个二叉树的根。现在在中序序列中找出 4 的位置。

1 2 3 4 5 6 7

也就是说可以得到二叉树的基本结构如下:

图1
4
/ \
1,2,3 5,6,7

再看后序序列剩下的元素:

2 3 1 5 7 6

最后一个元素是 6, 说明在 6 是根。

在中序序列中:

1 2 3 | 4 | 5 6 7

说明在 图1 中, 6 是右子树的根。

图2
4
/ \
1,2,3 6
/ \
5 7

继续遍历后序序列:

2 3 1 5 7

5 和 7 既是叶子节点也是一个特殊的根。

此时,后序序列剩下:

2 3 1

中序序列为:

1 2 3

显然, 1 是根, 2 和 3 是 1 的右子树。以此类推, 2 是 3 的左子树。那么中序序列和后序序列唯一确定的二叉树如下:

         4
/ \
1 6
\ / \
3 5 7
/
2

概括一下算法要点:

  • 从右往左遍历后序序列,得到根
  • 在中序序列中找到根,分离出左右子树
  • 对左右子树进行同样的操作

不难看出,是一个递归。

数据结构课程上,在纸上这类题目大家都会画出来,但是一到 Code 层面,完整实现还是有点难度的。

最后解析一下代码实现。

  • 参数 lr: 中序序列inorder[l...r], 代表当前所处理的子树
  • rootIdxPost: 后序序列中根的位置。(实际上取值变化就是: (N-1), ..., 0 )
Tree createTree(int l, int r, int &rootIdxPost)
{
if (l > r)
return NULL;
if (l == r)
{
Tree t = new TreeNode(inorder[l]);
rootIdxPost--;
return t;
}
int rootVal = postorder[rootIdxPost--];
int rootIdxIn = findRoot(inorder, rootVal);
Tree root = new TreeNode(rootVal);
root->right = createTree(rootIdxIn + 1, r, rootIdxPost);
root->left = createTree(l, rootIdxIn - 1, rootIdxPost);
return root;
}

完整代码:

#include <cstdio>
#include <vector>
#include <assert.h>
#include <queue>
#define NMAX 35
using namespace std;
struct TreeNode
{
int val;
TreeNode *left, *right;
TreeNode(int v = -1, TreeNode *l = NULL, TreeNode *r = NULL) : val(v), left(l), right(r) {}
};
typedef TreeNode *Tree;
vector<int> postorder(NMAX), inorder(NMAX);
int N = 0;
int findRoot(vector<int> &inorder, int rootVal)
{
size_t len = inorder.size();
for (size_t i = 0; i < len; i++)
{
if (inorder[i] == rootVal)
return i;
}
assert(0);
return -1;
}
Tree createTree(int l, int r, int &rootIdxPost)
{
if (l > r)
return NULL;
if (l == r)
{
Tree t = new TreeNode(inorder[l]);
rootIdxPost--;
return t;
}
int rootVal = postorder[rootIdxPost--];
int rootIdxIn = findRoot(inorder, rootVal);
Tree root = new TreeNode(rootVal);
root->right = createTree(rootIdxIn + 1, r, rootIdxPost);
root->left = createTree(l, rootIdxIn - 1, rootIdxPost);
return root;
}
void level(Tree root)
{
if (root == NULL)
return;
queue<Tree> q;
printf("%d", root->val);
if (root->left)
q.push(root->left);
if (root->right)
q.push(root->right);
while (!q.empty())
{
Tree p = q.front();
q.pop();
printf(" %d", p->val);
if (p->left)
q.push(p->left);
if (p->right)
q.push(p->right);
}
}
int main()
{
scanf("%d", &N);
for (int i = 0; i < N; i++)
{
scanf("%d", &postorder[i]);
}
for (int i = 0; i < N; i++)
{
scanf("%d", &inorder[i]);
}
int rootIdxPost = N - 1;
Tree root = createTree(0, N - 1, rootIdxPost);
level(root);
}

markdown写bolg,"那是真的niubility"。

最新文章

  1. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(24)-权限管理系统-将权限授权给角色
  2. [CentOs7]图形界面
  3. java的重载、覆盖和隐藏的区别
  4. mysql 设置编码 Incorrect string value: &#39;\xE9\x98\xBF\xE4\xB8\x89...&#39; for column &#39;cont,mysql乱码
  5. sysfs接口函数到建立_DEVICE_ATTR
  6. mysql慢查询优化之explain的各列含义
  7. 深入理解计算机系统第二版习题解答CSAPP 2.1
  8. DD-WRT相关资源
  9. android sql Cursor
  10. dubbo的简单实现
  11. 【原】Java学习笔记027 - 泛型
  12. LeetCode算法题-Binary Number with Alternating Bits(Java实现)
  13. 使用bootstrap-select有时显示“Nothing selected”
  14. 虚拟机下Linux安装jdk
  15. LCA&amp;最小生成树
  16. 12月7日,几个错误,拼写错误,遗漏符号:,记忆有误,max-width的作用。gem mini_magick, simple_form
  17. Session超时问题(AOP 过滤器)
  18. mac下zephir第一步,安装+hello zephir!
  19. Java并发(九):重入锁 ReentrantLock
  20. ubuntu下root不能复制 abc用户下的软连接文件

热门文章

  1. string类中getline函数的应用
  2. 8.【Spring Cloud Alibaba】配置管理-Nacos
  3. Ribbon进行服务调用/负载均衡以及请求重试配置
  4. bootstrap简介与入门
  5. windows 10 右键菜单注册表位置
  6. canvas初尝试
  7. VMware虚拟机从安装到激活再到创建虚拟机解决黑屏、卡、死机系列问题教程第二篇
  8. 《Javascript中 == 和 === 的区别》
  9. koa进阶史(一)
  10. 安装部署hyperledger fabric1.0