有一棵二叉树,每个节点由一个大写字母标识(最多26
个节点),现有两组字母,分别表示后序遍历 (左孩子->右孩子->父节点) 和中序遍历 (左孩子->父节点->右孩子) 的结果,请输出层次遍历的结果。
输入为两个字符串,分别是二叉树的后序遍历和中序遍历结果
输出二叉树的层次遍历结果
CBEFDA CBAEDF
ABDCEF
二叉树为
A
/ \
B D
/ / \
C E F
本题属于两道经典二叉树题目的结合
LeetCode106. 从中序与后序遍历构造二叉树 和 LeetCoe102. 二叉树的层序遍历
根节点A
一定是后序遍历结果中的最后一个元素。即
CBEFD | A
可以在中序遍历中定位到根节点A
,即
CB | A | EDF
↑
根节点
在中序遍历结果中,根节点的左边和右边分别是其左子树和右子树中序遍历的结果,即
CB | A | EDF
↑ ↑
左子树 右子树
可以得知,根节点的左子树的节点个数为2
,右子树的节点个数为3
。反映到后序遍历上,有
CB | EFD | A
↑ ↑
左子树 右子树
由于中序遍历和后序遍历都是递归的,因此对于其左子树和右子树的中序和后序遍历结果,又可以继续上述过程。直到子树构建完毕。其代码为
class TreeNode:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def buildTree(inorder, postorder):
dic = {val: i for i, val in enumerate(inorder)}
n = len(inorder)
return help(dic, postorder, inorder, n-1, 0, n-1)
def help(dic, postorder, inorder, post_end, in_start, in_end):
if in_start > in_end:
return None
node_val = postorder[post_end]
idx_node = dic[node_val]
node = TreeNode(node_val)
node.left = help(dic, postorder, inorder, post_end - (in_end - idx_node) - 1, in_start, idx_node - 1)
node.right = help(dic, postorder, inorder, post_end - 1, idx_node + 1, in_end)
return node
层序遍历就是经典的二叉树BFS过程,直接套模板即可。
def level_order_traverse(root):
ans = str()
q = deque()
q.append(root)
while q:
node = q.popleft()
ans += node.val
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return ans
# 题目:【DFS&BFS】2023C-二叉树的广度优先搜索
# 分值:200
# 作者:闭着眼睛学数理化
# 算法:DFS/BFS
# 代码看不懂的地方,请直接在群上提问
from collections import deque
# 构建树节点类
class TreeNode:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def buildTree(inorder, postorder):
dic = {val: i for i, val in enumerate(inorder)}
n = len(inorder)
# 递归入口
return help(dic, postorder, inorder, n-1, 0, n-1)
# 对于任何一棵子树:
# 根节点node一定位于该子树后序遍历数组的最后一个位置post_end,即可以计算得到node_val
# 根据node_val可以找到根节点node在中序遍历数组中的位置,其左边为左子树,右边为右子树
# 然后对左子树和右子树进行递归操作
def help(dic, postorder, inorder, post_end, in_start, in_end):
# 递归终止条件:若中序遍历区间不存在,返回空节点
if in_start > in_end:
return None
# 获得当前区间的根节点的值node_val,为postorder[post_end]
node_val = postorder[post_end]
# 获得该节点在中序遍历数组中的值
idx_node = dic[node_val]
# 构建节点node
node = TreeNode(node_val)
# 分别对node_val的左边和右边进行递归,得到左节点和右节点
node.left = help(dic, postorder, inorder, post_end - (in_end - idx_node) - 1, in_start, idx_node - 1)
node.right = help(dic, postorder, inorder, post_end - 1, idx_node + 1, in_end)
# 将该节点回传
return node
# 对根节点为root的二叉树进行层序遍历的函数,
# 直接套二叉树BFS模板
def level_order_traverse(root):
ans = str()
q = deque()
q.append(root)
while q:
node = q.popleft()
ans += node.val
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return ans
# 输入后序、中序遍历的结果字符串
postorder, inorder = input().split()
# 建树
root = buildTree(inorder, postorder)
# 层序遍历
ans = level_order_traverse(root)
# 输出结果
print(ans)
import java.util.*;
class TreeNode {
char val;
TreeNode left;
TreeNode right;
TreeNode(char val) {
this.val = val;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String postorder = scanner.next();
String inorder = scanner.next();
TreeNode root = buildTree(inorder, postorder);
String ans = levelOrderTraverse(root);
System.out.println(ans);
}
public static TreeNode buildTree(String inorder, String postorder) {
Map<Character, Integer> dic = new HashMap<>();
for (int i = 0; i < inorder.length(); i++) {
dic.put(inorder.charAt(i), i);
}
return help(dic, postorder.toCharArray(), inorder.toCharArray(), inorder.length() - 1, 0, inorder.length() - 1);
}
public static TreeNode help(Map<Character, Integer> dic, char[] postorder, char[] inorder, int postEnd, int inStart, int inEnd) {
if (inStart > inEnd) {
return null;
}
char nodeVal = postorder[postEnd];
int idxNode = dic.get(nodeVal);
TreeNode node = new TreeNode(nodeVal);
node.left = help(dic, postorder, inorder, postEnd - (inEnd - idxNode) - 1, inStart, idxNode - 1);
node.right = help(dic, postorder, inorder, postEnd - 1, idxNode + 1, inEnd);
return node;
}
public static String levelOrderTraverse(TreeNode root) {
StringBuilder ans = new StringBuilder();
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
TreeNode node = q.poll();
ans.append(node.val);
if (node.left != null) {
q.offer(node.left);
}
if (node.right != null) {
q.offer(node.right);
}
}
return ans.toString();
}
}
#include
#include
#include
using namespace std;
struct TreeNode {
char val;
TreeNode *left;
TreeNode *right;
TreeNode(char val) : val(val), left(nullptr), right(nullptr) {}
};
TreeNode *buildTree(unordered_map<char, int> &dic, string &postorder, string &inorder, int postEnd, int inStart, int inEnd) {
if (inStart > inEnd) {
return nullptr;
}
char nodeVal = postorder[postEnd];
int idxNode = dic[nodeVal];
TreeNode *node = new TreeNode(nodeVal);
node->left = buildTree(dic, postorder, inorder, postEnd - (inEnd - idxNode) - 1, inStart, idxNode - 1);
node->right = buildTree(dic, postorder, inorder, postEnd - 1, idxNode + 1, inEnd);
return node;
}
string levelOrderTraverse(TreeNode *root) {
string ans;
queue<TreeNode *> q;
q.push(root);
while (!q.empty()) {
TreeNode *node = q.front();
q.pop();
ans.push_back(node->val);
if (node->left) {
q.push(node->left);
}
if (node->right) {
q.push(node->right);
}
}
return ans;
}
int main() {
string postorder, inorder;
cin >> postorder >> inorder;
unordered_map<char, int> dic;
for (int i = 0; i < inorder.size(); ++i) {
dic[inorder[i]] = i;
}
TreeNode *root = buildTree(dic, postorder, inorder, inorder.size() - 1, 0, inorder.size() - 1);
string ans = levelOrderTraverse(root);
cout << ans << endl;
return 0;
}
时间复杂度:O(N)
。建树过程和层序遍历过程,均需遍历每一个节点。
空间复杂度:O(N)
。哈希表所占空间。
华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!
课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!
60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁
可上全网独家的欧弟OJ系统练习华子OD、大厂真题
可查看链接 大厂真题汇总 & OD真题汇总(持续更新)
绿色聊天软件戳 od1336
了解更多