题目链接
3
/ \
9 20
关于二叉树的遍历,其实有个比较好记的方法,假设有一个棵树,只有三个节点,左节点树,当前节点,右边节点。
假设需要打印中间节点(根节点),有三种输出方式
1.按照左、中、右,
9-3-20
由于中间节点在中间输出,称为前序遍历,同理
2.中、左、右
中序遍历
3-9-20
3.左、右、中
后续遍历
9-20-3
所以题目中的二叉树的遍历为
3
/ \
9 20
/ \
15 7
前序遍历(DLR),可记做根左右。前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。
3-9-20-15-7
中序遍历(LDR),中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。
9-3-15-20-7
后序遍历(LRD),首先遍历左子树,然后遍历右子树,最后访问根结点。
9-15-7-20-3
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
class Solution {
int i=0;
public TreeNode buildTree(int[] preorder, int[] inorder) {
int inoLen = inorder.length;
return myBuildTree(preorder, inorder, 0, inoLen - 1);
}
private TreeNode myBuildTree(int[] preorder, int[] inorder, int start, int end) {
//中止条件
if (start > end) {
return null;
}
int rootVal = preorder[i];
//找到左边树的
int left = start;
for (int i = 0; i <= end; i++) {
if (inorder[i] == rootVal) {
left = i;
}
}
//start -left-1 都是左边树 右边 left+1 到 end都是右边树
i++;
TreeNode root = new TreeNode(rootVal);
root.left = myBuildTree(preorder, inorder, start, left-1);
root.right = myBuildTree(preorder, inorder, left + 1, end);
return root;
}
}
1.首先分析前序遍历和中序遍历
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
从前序遍历的规律可以知道,3 二叉树的根节点,从中序遍历的特点(先输出左,再输出根,最后输出右),可以知道根节点3的左边只有一个节点9,后面的15 ,20 ,7是其右边树
先构建一棵树
3
/ \
9 待定[15,20,7]
再来分析右边树{15,20,7]
1.按照前序遍历得到右边的树的根节点是20,在从中序遍历,知道 左边是15,右边是7
20
/ \
15 7
最后将两课树组装
3
/ \
9 20
/ \
15 7
2.拆分
从上面的分析可以知道,我们如何使用前序和中序结合,构建二叉树的步骤
一、从前序遍历得到根节点
二,前序遍历得到右边树,右边树
2.1前序遍历先取值 3
中序遍历得到 左边 9, 右边 15,20,7
2.2前序遍历往后移一位,取值9
中序遍历得到 左边 null,右边 null
2.3 前序遍历往后移一位,取值20
中序遍历得到 左边 为15,右边 7
2.3 前序遍历往后移一位,取值15
中序遍历得到 左边 为null,右边 null
2.3 前序遍历往后移一位,取值7
中序遍历得到 左边 为null,右边 null
按照这个思路,我们可以写出规律
设置一个全局遍历i,维护前序遍历的左移动的位置
// 从前序遍历得到中间节点或者
int rootVal = preorder[i];
// 遍历中序得到 左边树到根节点的位置
for (int i = 0; i <= end; i++) {
if (inorder[i] == rootVal) {
left = i;
}
}
构建根节点的树
TreeNode root = new TreeNode(rootVal);
变量后移一位
i++;
以上就是整个遍历的循环体的代码
接下来要构建递归的的整体代码
1.参数
前序遍历,中序遍历,开始的位置,结束的位置
2.结束条件,开始的位置大于结束位置
if (start > end) {
return null;
}
3.循环体
int rootVal = preorder[i];
// 找到左边树的结束位置
//从开始位置累加到结束位置,如[15,20,7] 这里的开始位置就是 2
int left = start;
for (int i = 0; i <= end; i++) {
if (inorder[i] == rootVal) {
left = i;
}
}
i++;
TreeNode root = new TreeNode(rootVal);
4.递归左,右树
// start -left-1 都是左边树,右边 left+1 到 end都是右边树
root.left = myBuildTree(preorder, inorder, start, left-1);
root.right = myBuildTree(preorder, inorder, left + 1, end);
5.返回结果
return root;