java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846
1. 法一:递归
解题思路:时间复杂度O(n),空间复杂度O(n),空间使用了一个Map,大小为中心遍历的长度,以及递归需要的栈空间
因为后序遍历[9,15,7,20,3]是左右中,它表示一个区间中,最后一个结点,是中间结点。比如[9,15,7,20,3]这个区间,正好是整个二叉树,共5个结点。那么这个区间的中间结点,也就是根节点为最后一个结点3. 而中序遍历[9,3,15,20,7]是左中右,它表示,只要找到中间结点,就可以分出左右两个区间来,比如[9,3,15,20,7]这个区间,已知3是根节点,那么[9]在其左子树,[15,20,7]在其右子树 所以思路很简单,我们先通过后序遍历序列,在区间中拿到最后一个结点,从而获取中间结点。然后通过中序遍历序列,获得其左右两个区间 然后其左右两个区间,因为后序遍历是左右中,中确定后,先确定右区间。
继续从后序遍历序列中,获取其最后一个结点20,20就是这个右子树的中间结点。
然后构造其左区间。依次类推,直到整颗二叉树完成构造。
后序遍历序列只需要从后往前依次遍历即可,因为只需要你做一遍后序遍历,就会发现,后序遍历的效果就是每一个中间结点,都按顺序排列在序列末尾
比如[9,15,7,20,3],根节点为3,3的右子树为20,20的右子树为7,此时通过中序遍历发现右边到头了 开始左子树构造,20的左子树为15, 然后15到头了。回到3 , 最后3的左子树为9. 9也到头了,没有结点了,构造完成
所以一定要注意,拿到中间结点后,先去右区间,右区间遍历完成后,再去左区间
class Solution {
int post_idx;
int [ ] postorder;
int [ ] inorder;
Map < Integer , Integer > idx_map = new HashMap < Integer , Integer > ( ) ;
public TreeNode buildTree ( int [ ] inorder, int [ ] postorder) {
this . postorder = postorder;
this . inorder = inorder;
post_idx = postorder. length - 1 ;
int idx = 0 ;
for ( Integer val : inorder) {
idx_map. put ( val, idx++ ) ;
}
return helper ( 0 , inorder. length - 1 ) ;
}
public TreeNode helper ( int in_left, int in_right) {
if ( in_left > in_right) {
return null ;
}
int root_val = postorder[ post_idx] ;
TreeNode root = new TreeNode ( root_val) ;
int index = idx_map. get ( root_val) ;
post_idx-- ;
root. right = helper ( index + 1 , in_right) ;
root. left = helper ( in_left, index - 1 ) ;
return root;
}
}
2. 法二:迭代
思路分析:时间复杂度O(n),空间复杂度O(n),空间只用了队列来模拟递归的栈,无需map
将中序和后序都反过来:中序变为右中左,后序变成右左中 初始我们可以直接通过后序获取根结点root 而如果我们倒着遍历中序序列的话,正好获得到root的右区间 当我们发现倒着遍历中序,找到了root,那么剩下的是左区间的 然后重复这个过程即可
class Solution {
public TreeNode buildTree ( int [ ] inorder, int [ ] postorder) {
if ( postorder == null || postorder. length == 0 ) {
return null ;
}
TreeNode root = new TreeNode ( postorder[ postorder. length - 1 ] ) ;
Deque < TreeNode > stack = new LinkedList < TreeNode > ( ) ;
stack. push ( root) ;
int inorderIndex = inorder. length - 1 ;
for ( int i = postorder. length - 2 ; i >= 0 ; i-- ) {
int postorderVal = postorder[ i] ;
TreeNode node = stack. peek ( ) ;
if ( node. val != inorder[ inorderIndex] ) {
node. right = new TreeNode ( postorderVal) ;
stack. push ( node. right) ;
} else {
while ( ! stack. isEmpty ( ) && stack. peek ( ) . val == inorder[ inorderIndex] ) {
node = stack. pop ( ) ;
inorderIndex-- ;
}
node. left = new TreeNode ( postorderVal) ;
stack. push ( node. left) ;
}
}
return root;
}
}