题型一:105. 从前序与中序遍历序列构造二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
思路分析:
1、从前序遍历结果中找到树根节点的值: pretorder[index];
2、在中序遍历结果中找到根节点的位置rootIndex,将中序遍历分成两部分:
①左子树的节点数据范围:[ left ,rootIndex )
②左子树的节点数据范围:[rootIndex+1,right )
3、创建根节点:
①递归创建根的左子树;
②递归创建根的右子树;
实现代码:
class Solution {
// preorder:前序遍历结果
// inorder:中序遍历结果
// [left,right):标记在中序遍历中节点的位置范围
int index = 0;
private TreeNode reBuildTree(int[] preorder, int[] inorder, int left, int right){
if(index >= preorder.length || left>=right){
return null;
}
//前序找根节点 preorder[index]
//在中序遍历中找根的位置
//确认左右子树的区间
int rootindex = left;
while(rootindex<right){
if(inorder[rootindex]==preorder[index]){
break; //如果找到了,直接退出
}
rootindex++; //如果没找到,往后继续走
}
//创建根节点
TreeNode root = new TreeNode(preorder[index]);
++index;//根的位置还包括左子树/右子树的根 所以需要移动
//递归调用左子树[left,rootindex):
root.left = reBuildTree(preorder,inorder,left,rootindex);
//递归调用右子树[rootindex+1,right):
root.right = reBuildTree(preorder,inorder,rootindex+1,right);
return root;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
return reBuildTree(preorder, inorder,0,inorder.length);
}
}
【注意】:
关于前序里找根节点(index)的一个知识点:
在不断递归的过程中,index的值实际会发生变化,需要再递归中对index的改变带出到上一层递归中,但是参数index是按照int的方式传递的,在里层的递归中对index是按照int的方式传递的,在里层对Index所做的修改并不能够体现到外层递归中。
<解决办法>
1、参数int直接使用Integer方式传递 ------错误
Integer 中的内容是无法修改的,如果修改,实际虚拟机会重新创建一个index。
2、将index重新封装一种新的类型------正确(没有意义)
3、将index作为类的成员变量------正确(如上代码: int index = 0)
题型二:106. 从中序与后序遍历序列构造二叉树
根据一棵树的中序遍历与后序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
思路分析:
1、从后序遍历结果中找到树根节点的值: postorder[index];
2、在中序遍历结果中找到根节点的位置rootIndex,将中序遍历分成两部分:
①左子树的节点数据范围:[ left ,rootIndex )
②左子树的节点数据范围:[rootIndex+1,right )
3、创建根节点:
①递归创建根的右子树;
②递归创建根的左子树;
实现代码:
class Solution {
int index = 0 ;
private TreeNode buildTree(int[] inorder, int[] postorder,int left, int right) {
if(index<0 || left>=right){
return null;
}
int rootIndex = left;
while(rootIndex<right){
if(inorder[rootIndex]==postorder[index]){
break;
}
rootIndex++;//没找到 继续往后找
}
TreeNode root = new TreeNode(postorder[index]);
--index;//后序遍历根节点在最后 所以需要向前
//递归右子树
root.right=buildTree(inorder,postorder,rootIndex+1,right);
//递归左子树
root.left=buildTree(inorder,postorder,left,rootIndex);
return root;
}
public TreeNode buildTree(int[] inorder, int[] postorder) {
index=postorder.length-1;
return buildTree(inorder,postorder,0,postorder.length);
}
}