1.题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
限制:
0 <= 节点个数 <= 5000
2.分析
- 首先想到递归实现
- public void rebuild(TreeNode node, int start, int end, int[] preorder, int[] inorder);
- node是这次要构建的节点,start和end代表要构建的inorder的起始位置和结束位置
- 我采用中序构建,所以构建的顺序就是preorder中数的顺序,所以采用一个全局变量prePosition来记录该取第几个数。
- 在inorder[start, end]中找到preorder[prePosition]
- 然后分左子树,右子树,递归。
3.我的代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
static int prePosition = 0;
public TreeNode buildTree(int[] preorder, int[] inorder) {
TreeNode root = new TreeNode();
// 空数组直接返回null
if (preorder.length == 0)
return null;
rebuild(root, 0, preorder.length - 1, preorder, inorder);
prePosition = 0; //这个地方一定要注意,因为是static,而后台会多次调用此方法,注意每次计算要清0;
return root;
}
public void rebuild(TreeNode node, int start, int end, int[] preorder, int[] inorder) {
if (start == end) {
node.val = preorder[prePosition];
prePosition++;
return;
} else if (start > end){ // 对应只有一个数的数组情况
return;
}
node.val = preorder[prePosition];
int number = preorder[prePosition];
prePosition++;
int position = -1;
for (int i = start; i <= end; i++) {
if (inorder[i] == number) {
position = i;
break;
}
}
if (start <= position - 1) {
TreeNode leftNode = new TreeNode();
node.left = leftNode;
}
if (position + 1 <= end) {
TreeNode rightNode = new TreeNode();
node.right = rightNode;
}
rebuild(node.left, start, position - 1, preorder, inorder);
rebuild(node.right, position + 1, end, preorder, inorder);
}
}
4.题解代码
采用HashMap来存位置,太妙了!!
class Solution {
int[] preorder;
HashMap<Integer, Integer> dic = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
for(int i = 0; i < inorder.length; i++)
dic.put(inorder[i], i);
return recur(0, 0, inorder.length - 1);
}
TreeNode recur(int root, int left, int right) {
if(left > right) return null; // 递归终止
TreeNode node = new TreeNode(preorder[root]); // 建立根节点
int i = dic.get(preorder[root]); // 划分根节点、左子树、右子树
node.left = recur(root + 1, left, i - 1); // 开启左子树递归
node.right = recur(root + i - left + 1, i + 1, right); // 开启右子树递归
return node; // 回溯返回根节点
}
}