参考自:《剑指Offer——名企面试官精讲典型编程题》
以及博客:https://www.cnblogs.com/edisonchou/p/4741099.html
题目:重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1, 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建出二叉树并输出它的头结点。
主要思路:在二叉树的前序遍历序列中,第一个数字就是树根结点的值。但在中序遍历序列中,根结点的值在序列的中间,左子树的结点的值位于根结点的值的左边,而右子树的结点的值位于根结点的值的右边。因此,通过扫描中序遍历序列,找出根节点位置,进而划分该根节点的左右子树。最后,递归分别重建左子树和右子树。
例如:
1
/ \
2 3
/ / \
4 5 6
\ /
7 8
前序遍历序列:{1, 2, 4, 7, 3, 5, 6, 8 }
中序遍历序列:{4, 7, 2, 1,5, 3, 8, 6 }
根节点:1
左子树前序遍历序列:2, 4, 7
左子树中序遍历序列:4, 7, 2
右子树前序遍历序列:3, 5, 6, 8
右子树中序遍历序列:5, 3, 8, 6
然后递归分别重建左子树和右子树。
关键点:前序遍历特点:第一个元素为根节点。中序遍历特点:根节点左边为左子树,右边为右子树。递归。
时间复杂度:O(树长度),注:时间主要消耗在查找根节点位置
public class ReConstructBinaryTree {
public static void main(String[] args) {
int[] preOrder = {1, 2, 4, 7, 3, 5, 6, 8};
int[] inOrder = {4, 7, 2, 1, 5, 3, 8, 6};
// 1
// / \
// 2 3
// / / \
// 4 5 6
// \ /
// 7 8
TreeNode result = reconstructBinaryTree(preOrder, inOrder);
}
private static TreeNode reconstructBinaryTree(int[] preOrder, int[] inOrder) {
if (preOrder == null || inOrder == null) {
return null;
}
return rebuild(preOrder, inOrder, 0, preOrder.length - 1, 0, inOrder.length - 1);
}
/**
* Rebuild tree node.
*
* @param preOrder 前序遍历序列
* @param inOrder 中序遍历序列
* @param preStart 前序遍历开始位置
* @param preEnd 前序遍历结束位置
* @param inStart 中序遍历开始位置
* @param inEnd 中序遍历结束位置
* @return tree node
*/
private static TreeNode rebuild(int[] preOrder, int[] inOrder, int preStart, int preEnd, int inStart, int inEnd) {
if (preStart > preEnd) {
return null;
}
//前序遍历第一个元素就是根节点值
int rootVal = preOrder[preStart];
//中序遍历中的根节点位置
int inRootIndex = inStart;
while (inRootIndex <= inEnd) {
//在中序遍历中查找根节点位置
if (rootVal == inOrder[inRootIndex]) {
break;
} else {
inRootIndex++;
}
}
//左子树长度
int leftLength = inRootIndex - inStart;
//创建根节点
TreeNode rootNode = new TreeNode(rootVal);
int preLeftEnd = preStart + leftLength;
//创建左子树
rootNode.left = rebuild(preOrder, inOrder, preStart + 1, preLeftEnd,
inStart, inRootIndex - 1);
//创建右子树
rootNode.right = rebuild(preOrder, inOrder, preLeftEnd + 1, preEnd,
inRootIndex + 1, inEnd);
return rootNode;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}