这道题是一道中等题,但是我使用的是一个遍历迭代维护一个显式栈,真的好难啊,感觉就像一道困难题目一样,就连题解都看不懂,真的难受。不过好在递归比较好理解。递归就是用一个分治的思想,说白了就是让一个大问题分解成若干个小问题,然后解决每一个小问题,大问题也就解决了。
递归解法:这个解法主要是根据前序遍历数组(跟左右)和中序遍历数组(左根右)的特性进行递归,首先在前序数组中找到一个根节点,然后就是在中序遍历数组中找到根节点的位置,然后进行分解成左子树和右子树,接下来在左子树和右子树做同样的事情即可。
注意:
-
寻找根下标在中序遍历数组中时,常规解法可以使用一个for循环,更好的办法是使用hashmap对于中序遍历数组的(key)元素以及(value)下标进行储存(空间换时间)。这里也有一个比较好的解法,要是有兴趣的话可以了解一下[。](105. 从前序与中序遍历序列构造二叉树 - 力扣(Leetcode))当然我个人看来,这种比较巧妙的算法,主要了解一下就行了,追求极致的空间时间算法是没有必要的,代码容易理解、容易读懂也是很重要的。
-
递归时,一定要注意前序数组和中序数组的特性,进行分解左子树和右子树时,左子树p_start一定要前进变成一个新的根节点,p_end一定要注意千万不能直接就等于i_root_index,一定要计算左子树还有多少个结点,加上p_start+1才能为p_end,
public TreeNode buildTree(int[] preorder, int[] inorder) {
Map<Integer,Integer> map = new HashMap<>();
buildInorderMap(map,inorder);
return DFSBuildTree(0, preorder.length,preorder,0,inorder.length,inorder,map);
}
private TreeNode DFSBuildTree(int p_start, int p_end, int[] preorder, int i_start, int i_end, int[] inorder,Map<Integer,Integer> hashMap){
if (p_start == p_end) return null;
TreeNode node = new TreeNode(preorder[p_start]);
int i_root_index = hashMap.get(node.val);
// int i;
// for (i = i_start; i <i_end ; i++) {
// if (preorder[p_start] == inorder[i]) break;
// }
// 可以使用hashMap进行空间换时间。
// i_root_index = i;
int leftNumNodes = i_root_index - i_start;
node.left = DFSBuildTree(p_start+1,p_start+1+leftNumNodes,preorder,i_start,i_start+leftNumNodes,inorder,hashMap);
node.right = DFSBuildTree(p_start+1+leftNumNodes,p_end,preorder,i_root_index+1,i_end,inorder,hashMap);
return node;
}
private void buildInorderMap(Map map,int[] inorder){
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i],i);
}
}
加油啊,少年!!!!