题目
给前序遍历和中序遍历输出的数组
构造成二叉树
思路
- 前序遍历序列中的第一个元素为根节点,构建成根结点
- 找到该根节点在中序遍历序列中的位置,左侧即为左树的遍历序列,右侧为右树的遍历序列
-左树递归,右树递归,构建二叉树
代码
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length == 0 || inorder.length == 0)
return null;
TreeNode root = new TreeNode(preorder[0]);
for(int i = 0; i< inorder.length; i++){
if(preorder[0] == inorder[i]){
root.left = buildTree(Arrays.copyOfRange(preorder,1,i+1),Arrays.copyOfRange(inorder,0,i));
root.right = buildTree(Arrays.copyOfRange(preorder,i+1,preorder.length),Arrays.copyOfRange(inorder,i+1,inorder.length));
break;
}
}
return root;
}
}
复杂度分析
时间复杂度:O(n*n),其中 n 是树中的节点个数。每一次递归都要遍历中序序列找根结点。
空间复杂度O(n^2),因为每一次递归要创建额外的数组空间。
改善
- 不用每次都要创建一个数组,用变量记住子树的头尾
- 每一次都要for循环遍历中序序列来找根结点,可以使用hashmap来存储中序序列,这样每次找根结点只需要常数的时间。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
HashMap<Integer, Integer> map = new HashMap<>(); //将中序遍历放到哈希表中,数值是K,对应的下标是V.
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return buildTreeHelper(preorder, 0, preorder.length-1, inorder, 0, inorder.length-1, map);
}
private TreeNode buildTreeHelper(int[] preorder, int p_start, int p_end, int[] inorder, int i_start, int i_end,HashMap<Integer, Integer> map) {
if (p_start > p_end) { //当子区间没有元素
return null;
}
int root_val = preorder[p_start];
TreeNode root = new TreeNode(root_val); //创建一个根结点
int i_root_index = map.get(root_val); //根结点下标
int leftNum = i_root_index - i_start; //左子树个数
root.left = buildTreeHelper(preorder, p_start + 1, p_start + leftNum , inorder, i_start, i_root_index-1, map);
root.right = buildTreeHelper(preorder, p_start + leftNum + 1, p_end, inorder, i_root_index + 1, i_end, map);
return root;
}
}
复杂度分析
时间复杂度:O(n),其中 nn 是树中的节点个数。
空间复杂度:O(n),除去返回的答案需要的 O(n) 空间之外,我们还需要使用 O(n)的空间存储哈希映射,以及 O(h)的空间表示递归时栈空间。加起来也就是O(n)。