题目描述
英文
中文大意
给定二叉树的后序遍历 和 中序遍历序列,请输出二叉树的层次遍历
注意:我们假定二叉树中节点的值都是 唯一的正整数
第一行输入为 N
,第二行为后序遍历,第三行为 中序遍历
N<=30
样例
思路分析
此问题分为三个部分
- 通过后序遍历 和 中序遍历 构建二叉树
- 层次遍历此二叉树
分析后序遍历和中序遍历,我们发现:
后序遍历的最后一个节点必定是root
,我们根据root
可以把中序遍历分为 左子树 和 右子树,如此便可构建一个二叉树
code
#include <iostream>
#include <map>
#include <queue>
using namespace std;
// 用于存放中序遍历值的索引, 避免后续合并时每次要遍历中序遍历才能找到当时的节点
map<int, int> in_map;
// 用于最后的输出
int N = 0;
int cnt = 0;
typedef struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
};
TreeNode* divide(int post_order[], int post_left, int post_right, map<int, int> in_map, int in_left, int in_right) {
// 终止条件
if (post_left > post_right || in_left > in_right) {
return NULL;
}
TreeNode *root = new TreeNode;
// 根据后序遍历特性, 获取根节点
root->val = post_order[post_right];
// 获取该root节点的值在 中序遍历中的索引 如此可获得其左子树的个数和右子树的个数
// left: in_idx - in_left
// right: in_right - in_idx
int in_idx = in_map[root->val];
root->left = divide(post_order, post_left, post_left+(in_idx - in_left)-1, in_map, in_left, in_idx-1);
root->right = divide(post_order, post_right-(in_right-in_idx), post_right-1, in_map, in_idx+1, in_right);
return root;
}
// 层序遍历
void BFS(TreeNode *root) {
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
// 返回queue内的首部元素
TreeNode* node = q.front();
// 弹出首部元素
q.pop();
printf("%d", node->val);
cnt++;
if (cnt < N) {
printf(" ");
}
if (node->left != NULL) {
q.push(node->left);
}
if (node->right != NULL) {
q.push(node->right);
}
}
}
int main() {
scanf("%d", &N);
int post_order[N], in_order[N];
for(int i = 0;i < N;i++) {
int val;
scanf("%d", &val);
post_order[i] = val;
}
for(int i = 0;i < N;i++) {
int val;
scanf("%d", &val);
in_map[val] = i;
in_order[i] = val;
}
TreeNode *root = divide(post_order, 0, N-1, in_map, 0, N-1);
BFS(root);
return 0;
}
注意:TreeNode必须是返回指针类型,否则无法返回NULL
之前我在leetcode用java写过这样的题,今天用C++写…结果写的很难受
看来还是太菜了