我们先来看一下原题:
解题思路:
要想求出这道题的解,重建一个二叉树,我们要求出以下几点:
- 根节点的值
- 左右子树
这是一个大体思路。
要想求出根节点,我们要知道一个知识点。
前序数组的第一个元素就是根节点的值
然后问题就十分简单了。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
//求出根节点
TreeNode root=new TreeNode(preorder[0]);
//返回根节点
return root;
}
然后到了求左右子树的部分了,我们选择使用递归的方法,通过不断地将每个节点地前序数组和中序数组放进buildTree()来递归求解,最终返回我们要的左右节点。
//求出根节点的左子树buildTree(左子树的前序数组,左子树的中序数组)
root.left=buildTree(左子树的前序数组,左子树的中序数组);
//求出根节点的右子树(右子树的前序数组,左子树的中序数组)
root.right=buildTree(右子树的前序数组,左子树的中序数组);
那么,问题就来了,怎么知道左右节点的前序数组和中序数组呢?
这又涉及到另外一个知识点了:
中序数组以当前节点的根节点为界,左面的,就是该节点的左子树部分,根节点右面,就是右子树部分
就比如体中的例子:
inorder = [9,3,15,20,7] 根节点为3,左面是他的左子树,单个节点值为9,而右面是它的右子树 ,节点一堆
于是,我们再进一步写出我们的题解:
先写一个函数,帮我们不断求出当前结点在中序数组的下标
public int findNode(int []preorder,int[] inorder){
for(int i=0;i<inorder.length;i++){
if(inorder[i]==preorder[0]) return i;
}
return 0;
}
然后我们要使用一个函数Arrays.copyOfRange(T[ ] original,int from,int to)
,帮我们截取当前节点的前序数组和中序数组。
//求出根节点的左子树buildTree(左子树的前序数组,左子树的中序数组)
root.left=buildTree(Arrays.copyOfRange(preorder,1,index+1),Arrays.copyOfRange(inorder,0,index));
//求出根节点的右子树(右子树的前序数组,左子树的中序数组)
root.right=buildTree(Arrays.copyOfRange(preorder,index+1,preorder.length),Arrays.copyOfRange(inorder,index+1,inorder.length));
Arrays.copyOfRange(T[ ] original,int from,int to) 用法:
将一个原始的数组original,从下标from开始复制,复制到上标to,生成一个新的数组。
注意这里包括下标from,不包括上标to。
然后再设置递归结束条件,就大功告成了!
//递归退出条件(前序数组为空或者前序数组长度为0)
if(preorder==null||preorder.length==0) return null;
最终答案是这样子的(可以直接cv):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
//递归退出条件(前序数组为空或者前序数组长度为0)
if(preorder==null||preorder.length==0) return null;
//接收下根节点的位置
int index=findNode(preorder,inorder);
//求出根节点
TreeNode root=new TreeNode(preorder[0]);
//求出根节点的左子树buildTree(左子树的前序数组,左子树的中序数组)
root.left=buildTree(Arrays.copyOfRange(preorder,1,index+1),Arrays.copyOfRange(inorder,0,index));
//求出根节点的右子树(右子树的前序数组,左子树的中序数组)
root.right=buildTree(Arrays.copyOfRange(preorder,index+1,preorder.length),Arrays.copyOfRange(inorder,index+1,inorder.length));
//返回根节点
return root;
}
//搜寻函数,寻找中序遍历里根节点的序号
public int findNode(int []preorder,int[] inorder){
for(int i=0;i<inorder.length;i++){
if(inorder[i]==preorder[0]) return i;
}
return 0;
}
}