这道题的递归解法其实就是,用递归的方法把我们通过前序遍历和中序遍历构造二叉树的思路表达出来。
先序遍历的顺序是,根节点,左节点,右节点。
中序遍历的顺势是,左节点,根节点,右节点
如图所示,我们每次都可以根据先序数组中目前的根节点,找到中序数组中根节点的位置,通过,得到当前左子树,右子树的情况,来构建当前的树,再递归去处理,左子树和右子树
在代码实现上,我们通过指针的方式去记录当前的先序数组和中序数组中的开头与结尾,从而去构建树
当前树
左子树
右子树
代码实现:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
int pn = preorder.length;
int in = inorder.length;
return build(preorder,0 ,pn, inorder,0, in);
}
private TreeNode build(int[] preorder,int p_start, int p_end, int[] inorder, int i_start, int i_end) {
if(p_start == p_end) return null;
int root_val = preorder[p_start];
TreeNode root = new TreeNode(root_val);
int root_index_i = 0;
//查找当前根节点在中序数组中的位置
for(int i = 0; i < inorder.length; i++) {
if(root_val == inorder[i]) {
root_index_i = i;
break;
}
}
int left_num = root_index_i - i_start;
root.left = build(preorder, p_start + 1, p_start + left_num + 1, inorder,i_start, root_index_i);
root.right = build(preorder,p_start + left_num + 1, p_end, inorder, root_index_i + 1, i_end);
return root;
}
}
但是会发现,我们其实不需要每次都去中序数组中找当前节点的位置,所以,可以预先将中序数组存到Map中,实现O(1)的一个查询,这里就没有再写了。
信息来源:105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode) 题解大佬还讲解了其他优化方式,感兴趣的小伙伴可以去了解一下