首先要懂得前序遍历和中序遍历,可以写出两个数组,自己手动来重建一下二叉树,来看看重建二叉树是怎么一个流程。
以图中给出的二叉树为例,
根据前序遍历的特点,可知前序遍历的首尾数字是根节点,比如这个时候根节点数值为3,可以在中序遍历中第2个位置找到数值3,在3左边的9为3的左子树,右边的15,20,7为右子树。同时可以把前序 数组划分为两个数组,即左子树的前序遍历数组9,右子树的前序遍历数组20,15,7,采用递归的方式进行求解。
我自己的写法中,是以中序遍历为依据返回节点的。当中序遍历数组的左边指针超过了右边指针,则说明越过了叶子节点,应该返回null;当左边指针与右边指针重合时,说明找到了当前根节点的左子节点或者右子节点,返回这个节点即可。
我的代码:
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder == null || preorder.length < 1 || inorder == null || inorder.length < 1) return null;
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return getAns(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1, map);
}
private TreeNode getAns(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd, Map<Integer, Integer> map) {
//递归终止条件
if (inStart > inEnd) return null;
if (inStart == inEnd) return new TreeNode(inorder[inStart]);
TreeNode root = new TreeNode(preorder[preStart]);
int index = map.get(preorder[preStart]);
int leftNum = index - inStart;
root.left = getAns(preorder, preStart + 1, preStart + leftNum, inorder, inStart, index - 1, map);
root.right = getAns(preorder, preStart + leftNum + 1, preEnd, inorder, index + 1, inEnd, map);
return root;
}
}
路飞代码:
class Solution {
HashMap<Integer, Integer> dic = new HashMap<>();
int[] po;
public TreeNode buildTree(int[] preorder, int[] inorder) {
po = preorder;
for(int i = 0; i < inorder.length; i++)
dic.put(inorder[i], i);
return recur(0, 0, inorder.length - 1);
}
TreeNode recur(int pre_root, int in_left, int in_right) {
if(in_left > in_right) return null;
TreeNode root = new TreeNode(po[pre_root]);
int i = dic.get(po[pre_root]);
root.left = recur(pre_root + 1, in_left, i - 1);
root.right = recur(pre_root + i - in_left + 1, i + 1, in_right);
return root;
}
}
官方代码(我的代码格式与官方代码类似,只是路飞和官方都是以前序遍历为依据返回节点的)
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder == null || preorder.length == 0) {
return null;
}
Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>();
int length = preorder.length;
for (int i = 0; i < length; i++) {
indexMap.put(inorder[i], i);
}
TreeNode root = buildTree(preorder, 0, length - 1, inorder, 0, length - 1, indexMap);
return root;
}
public TreeNode buildTree(int[] preorder, int preorderStart, int preorderEnd, int[] inorder, int inorderStart, int inorderEnd, Map<Integer, Integer> indexMap) {
if (preorderStart > preorderEnd) {
return null;
}
int rootVal = preorder[preorderStart];
TreeNode root = new TreeNode(rootVal);
if (preorderStart == preorderEnd) {
return root;
} else {
int rootIndex = indexMap.get(rootVal);
int leftNodes = rootIndex - inorderStart, rightNodes = inorderEnd - rootIndex;
TreeNode leftSubtree = buildTree(preorder, preorderStart + 1, preorderStart + leftNodes, inorder, inorderStart, rootIndex - 1, indexMap);
TreeNode rightSubtree = buildTree(preorder, preorderEnd - rightNodes + 1, preorderEnd, inorder, rootIndex + 1, inorderEnd, indexMap);
root.left = leftSubtree;
root.right = rightSubtree;
return root;
}
}
}