首先我们要明白先中后序遍历的特点:
- 先序遍历中 第一个一定是根结点。
- 中序遍历中 根结点左子树的所有结点一定在根结点的左边,右子树的所有结点一定在根结点的右边。所有中序遍历的序列组成可以表示为 :左子树结点+根结点+右子树结点。
- 后序遍历中 最后一个结点一定是根结点。**
根据先序遍历和中序遍历构建二叉树
解题细想:
- 设置变量inedx 方便从preorder数组中获取元素构建结点。
- 判断inedx的合法性,防止我们在最终的递归途中数组越界异常。
- 中序遍历中根结点可以作为一道分界线,他的左边是他的左子树结点,右边是右子树结点,所以一开始的nodeLeft 为0 nodeRight为中序遍历数组的长度。
- 根结点就是先序遍历的第一个结点,构建根结点,然后 index++(方法中index只加一次是因为在preorder数组中index下标的元素只可能是左结点或者右结点)。
- 构建根结点的左结点,(在此之前我们要在中序遍历中找到根结点元素的下标pos),我们知道 中序遍历的序列组成可以表示为 :左子树结点+根结点+右子树结点 所以,根结点的左结点一定在pos之前。
- 然后我们进行递归进行判断nodeLeft 和nodeRight(就是上一个方法传来的pos值)的合法性,只要nodeLeft不是大于等于nodeRight 就说明在根结点下标的左边有元素,也就是说根结点的左子树不为空。构建该结点然后再次进行递归判断。
- 直到根结点的左子树的根结点建立完,此时就要建立根节点的子树、
- 此时传入的nodeLeft为pos+1和一开始的nodeRight,然后进行递归处理,只要 nodeLeft不是大于等于nodeRight 就说明在根结点下标的右边有元素,也就是说明有右子树,构建它。
代码如下:
//根据一棵树的前序遍历与中序遍历构造二叉树。
class Solution {
private int index = 0;
public TreeNode buildTree(int[] preorder, int[] inorder) {
index = 0;
return myBuildTree(preorder, inorder, 0, preorder.length);
}
public TreeNode myBuildTree(int[] preorder, int[] inorder, int indexLeft, int indexRight) {
if(indexLeft >= indexRight) {
return null;
}
if(index >= inorder.length) {
return null;
}
TreeNode node = new TreeNode(preorder[index]);
index ++;
int pos = findNodePos(inorder, node.val);
node.left = myBuildTree(preorder, inorder, indexLeft, pos);
node.right = myBuildTree(preorder, inorder, pos + 1, indexRight);
return node;
}
private int findNodePos(int[] inorder, int val) {
for (int i = 0; i < inorder.length; i++) {
if(inorder[i] == val) {
return i;
}
}
return -1;
}
}
根据后序遍历和中序遍历构建二叉树:
解题思想:
- 只要把上面的题回了,这道题很简单的。
- 首先后序遍历的最后一个结点是根结点,所以一开始index=数组的长度-1.
- 上面那道题是先建立左子树,再建立右子树,而这道题是后序遍历,所以要先建立右子树,再建立左子树。
- 其他递归条件和上一道题一样。
class Solution {
private int index = 0;
public TreeNode buildTree(int[] inorder, int[] postorder) {
index = postorder.length - 1;
return myBuildTree(inorder, postorder, 0, postorder.length);
}
public TreeNode myBuildTree(int[] inorder, int[] postorder, int indexLeft, int indexRight) {
if(indexLeft >= indexRight) {
return null;
}
if(index < 0) {
return null;
}
TreeNode node = new TreeNode(postorder[index]);
index --;
int pos = findNodePos(inorder, node.val);
node.right = myBuildTree(inorder, postorder, pos + 1, indexRight);
node.left = myBuildTree(inorder, postorder, indexLeft, pos);
return node;
}
private int findNodePos(int[] inorder, int val) {
for(int i = 0; i < inorder.length; i ++) {
if(inorder[i] == val) {
return i;
}
}
return -1;
}
}