给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]
提示:
1 <= preorder.length <= 3000
inorder.length == preorder.length
-3000 <= preorder[i], inorder[i] <= 3000
preorder
和 inorder
均 无重复 元素inorder
均出现在 preorder
preorder
保证 为二叉树的前序遍历序列inorder
保证 为二叉树的中序遍历序列解法:
解题之前先准备好需要的类。一个TreeNode(题目要求),一个TreeNode的工具类(用于层级打印Tree),由于树类型的题,这两个类出现较为频繁,因此,我单独抽出到公共模块中。
TreeNode:
/**
* @author bwzfy
* @ClassName TreeNode
* @create 2024/1/24 - 14:47
* @Version 1.0
**/
public class TreeNode {
public Integer val;
public TreeNode left;
public TreeNode right;
public TreeNode(Integer val) {
this.val = val;
}
public TreeNode(Integer val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
TreeNodeUtils:
import java.util.ArrayDeque;
import java.util.Queue;
/**
* @author bwzfy
* @ClassName TreeNodeUtils
* @create 2024/1/24 - 17:03
* @Version 1.0
**/
public class TreeNodeUtils {
/**
* 层级打印TreeNode
* @param root
*/
public static void levelPrintTreeNode(TreeNode root) {
Queue<TreeNode> queue = new ArrayDeque<>();
queue.add(root);
StringBuilder sb = new StringBuilder("[");
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node.val == null) {
sb.append("null, ");
continue;
}else {
sb.append(node.val + ", ");
}
if (node.left != null) {
queue.add(node.left);
}else {
queue.add(new TreeNode(null));
}
if (node.right != null) {
queue.add(node.right);
}else {
queue.add(new TreeNode(null));
}
}
sb.append("]");
System.out.println(sb);
}
}
看到这道题的时候,脑海中第一反应就是递归,递归逻辑即为拿整个先序遍历数组和整个中序遍历数组生成TreeNode
代码如下:
/**
* @author bwzfy
* @ClassName _105从前序与中序遍历序列构造二叉树
* @create 2024/1/24 - 14:18
* @Version 1.0
**/
public class _105从前序与中序遍历序列构造二叉树 {
public static void main(String[] args) {
int[] preorder = {3, 9, 20, 15, 7};
int[] inorder = {9, 3, 15, 20, 7};
TreeNode treeNode = buildTree(preorder, inorder);
TreeNodeUtils.levelPrintTreeNode(treeNode);
}
public static TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder.length == 0 || inorder.length == 0) {
return null;
}
return buildTreeSolve(preorder, 0, preorder.length, inorder, 0, inorder.length);
}
private static TreeNode buildTreeSolve(int[] preorder, int pStart, int pEnd, int[] inorder, int iStart, int iEnd) {
if (pStart >= pEnd || iStart >= iEnd) {
return null;
}
TreeNode root = new TreeNode(preorder[pStart]);
if (pEnd - pStart == 1 || iEnd - iStart == 1) {
return root;
}
// 中序遍历找到根节点的位置
int iRootIndex = 0;
for (int i = iStart; i < iEnd; i++) {
if (inorder[i] == preorder[pStart]) {
iRootIndex = i;
break;
}
}
int leftNum = iRootIndex - iStart;
// 递归构造左树
root.left = buildTreeSolve(preorder, pStart + 1, pStart + leftNum + 1, inorder, iStart, iRootIndex);
// 递归构造右树
root.right = buildTreeSolve(preorder, pStart + leftNum + 1, pEnd, inorder, iRootIndex + 1, iEnd);
return root;
}
}