LeetCode 107 从中序遍历与后序遍历构造二叉树 题解
根据一棵树的中序遍历与后序遍历构造二叉树。
类比:根据一棵树的中序遍历与前序遍历构造二叉树 #105。
注意:
你可以假设树中没有重复的元素。
例如,给出
中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
方法:递归
先放自己写的:
时间复杂度:最坏情况下为一条链,T(N)=T(N-1)+O(N)【用来查找根节点在inoder中的坐标】,时间的复杂度为O(N^2),最好情况下T(N)=T(N/2)+O(N),时间的复杂度为O(NlogN)
空间复杂度:O(h),h为二叉树的高度
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder == null || inorder.length == 0 || postorder == null || postorder.length == 0){
return null;
}
return treeBuild(inorder, postorder, 0, inorder.length - 1, 0, postorder.length - 1);
}
public TreeNode treeBuild(int[] inorder, int[] postorder,int inStart,int inEnd,int postStart,int postEnd){
int val = postorder[postEnd];
TreeNode root=new TreeNode(val);
int i = inStart;
for(; i <= inEnd; ++i){
if(inorder[i] == val){
break;
}
}
int leftLength = i - inStart;
int rightLength = inEnd - i;
root.left = (leftLength==0) ? null : treeBuild(inorder, postorder, inStart, i - 1, postStart, postStart + leftLength - 1);
root.right = (rightLength==0) ? null : treeBuild(inorder, postorder, i + 1, inEnd, postStart + leftLength, postEnd - 1);
return root;
}
官方题解:主要是利用hashmap存储中序遍历序列中的(结点值,索引值)对,利用O(1)的时间查找根节点在inOder数组中的索引值,当然这是在用空间换时间;再有就是可以逆序遍历postOder数组,作为根节点的值,不用维护这个数组的左右边界了,但是要注意的是,根据后序遍历的规则,这样应该是先递归右子树,再递归左子树
时间复杂度:O(n),其中 nn 是树中的节点个数。
空间复杂度:O(n)。我们需要使用 O(n) 的空间存储哈希表,以及 O(h)(其中 h 是树的高度)的空间表示递归时栈空间。这里 h<n,所以总空间复杂度为 O(n)。
class Solution {
int prePost;
HashMap<Integer,Integer> map = new HashMap<>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder == null || inorder.length == 0 || postorder == null || postorder.length == 0){
return null;
}
for(int i = 0; i < inorder.length; ++i){
map.put(inorder[i], i);
}
prePost = postorder.length - 1;
return treeBuild(inorder, postorder, 0, inorder.length - 1);
}
public TreeNode treeBuild(int[] inorder, int[] postorder,int inStart,int inEnd){
int val = postorder[prePost];
TreeNode root=new TreeNode(val);
int i = map.get(val);//根节点在inoder数组中的坐标
--prePost;//指向逆序后序遍历的下一个根节点
int leftLength = i - inStart;
int rightLength = inEnd - i;
//先递归右子树
root.right = (rightLength==0) ? null : treeBuild(inorder, postorder, i + 1, inEnd);
root.left = (leftLength==0) ? null : treeBuild(inorder, postorder, inStart, i - 1);
return root;
}
}