重建二叉树问题
重建二叉树问题
作者:Grey
原文地址:
说明
本题涉及到二叉树的各种遍历,对于二叉树的各种遍历,可以参考二叉树的先,中,后序遍历(递归,非递归)
根据中序遍历和后序遍历重建二叉树
链接地址:LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal
特别注意,本题的约束条件中,一定要保证inorder 和 postorder 都由不同的值组成。由于
中序遍历的顺序是:左 -> 中 -> 右
后序遍历的顺序是:左 -> 右 -> 中
所以对一棵树,如果其中序遍历的样子如下
后序遍历的样子如下
定义递归函数
TreeNode f(中序遍历结果, int L1, int R1, 后序遍历结果, int L2, int R2)
递归含义表示:通过中序遍历的L1...R1
和后序遍历L2...R2
构造出二叉树,返回根节点。
所以主函数调用
f(inorder, 0, L, postorder, 0, L);
即为答案。
接下来实现这个递归函数,由于后序遍历的最后一个节点就是树的根节点,所以
即:
树的根节点 = new TreeNode(后序遍历最后一个节点);
然后找到这个树的根节点在中序遍历的位置,假设在如下 index 位置上:
那么在中序遍历中,左树为[L1...(index - 1)]
,中序遍历的剩下部分用来构造右树:[(index + 1)... R1]
,
所以递归函数关于中序数组的几个参数可以确定下来
root.left = f(inorder, L1, index - 1, postorder, ?, ?);
root.right = f(inorder, index + 1, R1, postorder, ?, ?);
接下来就是确定问号部分该怎么设置,即后序遍历的数组哪些用来构成左树,哪些构成右树,
如下示意图,在后序遍历中,左树通过区间[L2...(L2 + index - L1 - 1)]
来构造
后序遍历的剩下部分用来构造右树:[L2 + index - L1...R2 - 1]
由于要记录某个节点在中序遍历中的位置,所以需要准备一个哈希表,用于存某个元素在中序遍历的位置。
int L = inorder.length - 1;
Map<Integer, Integer> m = new HashMap<>();
for (int i = 0; i <= L; i++) {
m.put(inorder[i], i);
}
完整代码如下
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (null == postorder || inorder == null || postorder.length != inorder.length) {
return null;
}
int L = inorder.length - 1;
Map<Integer, Integer> m = new HashMap<>();
for (int i = 0; i <= L; i++) {
m.put(inorder[i], i);
}
return f(inorder, 0, L, postorder, 0, L, m);
}
private TreeNode f(int[] inorder, int L1, int R1, int[] postorder, int L2, int R2, Map<Integer, Integer> m) {
// 这种
if (L2 > R2) {
return null;
}
TreeNode root = new TreeNode(postorder[R2]);
// 如果只有一个节点,则直接返回
if (L2 == R2) {
return root;
}
int index = m.get(postorder[R2]);
root.left = f(inorder, L1, index - 1, postorder, L2, L2 + index - L1 - 1, m);
root.right = f(inorder, index + 1, R1, postorder, L2 + index - L1, R2 - 1, m);
return root;
}
}
根据先序遍历和中序遍历重建二叉树
链接地址:LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal
对于一棵树,中序遍历的样子如下
先序遍历的样子如下
而且,先序遍历的第一个节点,就是根节点,然后定位根节点在中序遍历的位置,假设在 index 位置,则
中序遍历中,左树为[L2...(index - 1)]
,剩余部分[(index + 1)...R2]
去构造右树。
先序遍历中,左树为[(L1 + 1)...(index - L2 + L1)]
,剩余部分[(index - L2 + L1 + 1)...R1]
去构造右树。
完整代码如下
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (null == preorder || inorder == null || preorder.length != inorder.length) {
return null;
}
int L = inorder.length - 1;
Map<Integer, Integer> m = new HashMap<>();
for (int i = 0; i <= L; i++) {
m.put(inorder[i], i);
}
return f(preorder, 0, L, inorder, 0, L, m);
}
private TreeNode f(int[] preorder, int L1, int R1, int[] inorder, int L2, int R2, Map<Integer, Integer> m) {
if (L1 > R1) {
return null;
}
TreeNode root = new TreeNode(preorder[L1]);
if (L1 == R1) {
return root;
}
int index = m.get(preorder[L1]);
root.left = f(preorder, L1 + 1, index - L2 + L1, inorder, L2, index - 1, m);
root.right = f(preorder, index - L2 + L1 + 1, R1, inorder, index + 1, R2, m);
return root;
}
}
更多
本文来自博客园,作者:Grey Zeng,转载请注明原文链接:https://www.cnblogs.com/greyzeng/p/16715432.html