剑指 Offer 07. 重建二叉树
剑指 Offer 07. 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
限制:
0 <= 节点个数 <= 5000
思路
前序遍历的第一个节点,肯定是根节点
然后,根据根节点,遍历中序数组,找到对应的值,找到其下标index
那么,中序遍历[inLeft, index - 1]为树的左子树
中序遍历[index + 1, inRight]为树的右子树
然后继续递归左子树,右子树
没做出来。。。
参考了这哥们的解法
我们只需要使用3个指针即可:
一个是preStart,他表示的是前序遍历开始的位置
一个是inStart,他表示的是中序遍历开始的位置,
一个是inEnd,他表示的是中序遍历结束的位置
我们主要是对中序遍历的数组进行拆解,只要找到了前序遍历的结点在中序遍历的位置,我们就可以把中序遍历数组分解为两部分了。
如果index是前序遍历的某个值在中序遍历数组中的索引,以index为根节点划分的话,那么:
第一个根节点为3,在中序遍历3的index=1
中序遍历中[0,index-1]就是根节点左子树的所有节点,
[index+1,inorder.length-1]就是根节点右子树的所有节点。
中序遍历好划分,那么前序遍历呢?
如果是左子树:preStart=preStart+1;
preStart后面一个
如果是右子树就稍微麻烦点:
preStart = preStart+(index-instart+1);
preStart是当前节点比如m先序遍历开始的位置,index-instart+1就是当前节点m左子树的数量加上当前节点的数量,所以preStart+(index-instart+1)就是当前节点m右子树前序遍历开始的位置,我们来看下完整代码
public TreeNode buildTree(int[] preorder, int[] inorder) {
return helper(0, 0, inorder.length - 1, preorder, inorder);
}
public TreeNode helper(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder) {
if (preStart > preorder.length - 1 || inStart > inEnd) {
return null;
}
//创建结点
TreeNode root = new TreeNode(preorder[preStart]);
int index = 0;
//找到当前节点root在中序遍历中的位置,然后再把数组分两半
for (int i = inStart; i <= inEnd; i++) {
if (inorder[i] == root.val) {
index = i;
break;
}
}
root.left = helper(preStart + 1, inStart, index - 1, preorder, inorder);
root.right = helper(preStart + index - inStart + 1, index + 1, inEnd, preorder, inorder);
return root;
}
这哥们还找出了前序遍历的部分
前序遍历的左子树为[preLeft, N]
前序遍历的右子树为[N, preRight]
N = preLeft + (index - inLeft + 1)
在这哥们的思路下,完善了自己的代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
//边界条件
if(preorder == null || inorder == null) return null;
if(preorder.length == 0 || inorder.length == 0) return null;
if(preorder.length != preorder.length) return null;
return buildTree(preorder, inorder, 0, 0, preorder.length - 1);
}
public TreeNode buildTree(int[] preorder, int[] inorder, int preLeft, int inLeft, int inRight) {
//preLeft一直在加,最大不能超过preorder.length - 1
//inLeft也在加 inLeft < inorder.length - 1;
//inRight在减 inRight > 0;
if(preLeft > preorder.length - 1 || inLeft > inorder.length - 1 || inRight < 0 || inLeft > inRight){
return null;
}
TreeNode root = new TreeNode();
root.val = preorder[preLeft];
int midIndex = 0;
for(int i = inLeft; i <= inRight; i++){
if(root.val == inorder[i])
{
midIndex = i;
break;
}
}
root.left = buildTree(preorder, inorder, preLeft + 1, inLeft, midIndex - 1);
root.right = buildTree(preorder, inorder, preLeft + (midIndex - inLeft + 1), midIndex + 1, inRight);
return root;
}
}