题目描述
现有一棵
n
个结点的二叉树(结点编号为从0
到n-1
),已知其层序序列和中序序列,求先序序列。
输入描述
第一行一个整数
n(1≤n≤50)
,表示二叉树的结点个数;第二行为
n
个整数,表示二叉树的层序序列;第三行为
n
个整数,表示二叉树的中序序列。
输出描述
输出
n
个整数,表示二叉树的先序序列,中间用空格隔开,行末不允许有多余的空格。
样例
输入
6
0 2 5 1 4 3
1 2 4 0 5 3
输出
0 2 1 4 5 3
![image-20230301200928546](https://i-blog.csdnimg.cn/blog_migrate/07fbea721ca17f4f366bba0fbbdb90f9.png)
思路分析
-
总体的思路和已知前序/后序
+
中序序列构建二叉树类似,将构建过程拆分为左子树,根部,右子树三个部分,难点在于如何将层序遍历的序列拆分为左,根,右三个部分 -
首先,层序遍历的第一个元素在当前子树中一定是根节点,由此完成了拆分根节点的目标
其次,由于知道了根节点,因此我们可以通过根节点将左右子树进行划分,也就是说我们知道左子树和右子树具体都有哪些元素。
因此,只需要利用哈希表
leftMap<Integer,Boolean>
将层序序列中左子树的部分标记为true
即可,此时剩下未被标记的部分即为右子树,至此我们达成了将层序遍历序列划分为左,根,右三个部分的目标 -
接着便像前序
+
中序构建二叉树一样进行类似的处理就好,每次从层序序列中出队首元素作为根节点root
,得到根节点在中序序列中的位置,将属于左子树的节点划分进队列leftTree
,剩余划分进rightTree
-
root
的左子树即为中序序列中的左子树部分以及层序序列的左子树部分进行处理返回的结果,右子树同理
代码实现
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Scanner;
import javax.swing.text.AbstractDocument.LeafElement;
public class Main {
static ArrayList<Integer> res = new ArrayList<Integer>();
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
LinkedList<Integer> layerList = new LinkedList<Integer>();
int midArr[] = new int[n];
for (int i = 0; i < n; i++) {
// 层序序列
layerList.addLast(scanner.nextInt());
}
for (int i = 0; i < n; i++) {
midArr[i] = scanner.nextInt();
}
TreeNode root = buildTreeByLayerAndMid(layerList, midArr, 0, n - 1);
preOrder(root);
for (int i = 0; i < n; i++) {
System.out.print(res.get(i));
if (i < n - 1) {
System.out.print(" ");
}
}
}
public static TreeNode buildTreeByLayerAndMid(LinkedList<Integer> layerList, int midArr[], int left2, int right2) {
if (layerList.isEmpty()) {
return null;
}
// 当前节点若属于左子树则value为true
HashMap<Integer, Boolean> leftMap = new HashMap<Integer, Boolean>();
TreeNode root = new TreeNode(layerList.poll());
int count = 0;
for (int i = left2; i <= right2; i++) {
// 找到了根节点
if (midArr[i] == root.val) {
break;
}
// 当前遍历到的部分属于左子树
leftMap.put(midArr[i], true);
count++;
}
LinkedList<Integer> leftTree = new LinkedList<Integer>();
LinkedList<Integer> rightTree = new LinkedList<Integer>();
for (Integer integer : layerList) {
if (leftMap.getOrDefault(integer, false)) {
leftTree.addLast(integer);
} else {
rightTree.addLast(integer);
}
}
// left2+count指向根节点,因此-1后是左子树右边界
root.left = buildTreeByLayerAndMid(leftTree, midArr, left2, left2 + count - 1);
root.right = buildTreeByLayerAndMid(rightTree, midArr, left2 + count + 1, right2);
return root;
}
public static void preOrder(TreeNode root) {
if (root == null) {
return;
}
res.add(root.val);
preOrder(root.left);
preOrder(root.right);
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
public TreeNode() {
}
}