《剑指offer》—— 4. 重建二叉树(Java)
推荐
完整《剑指Offer》算法题解析系列请点击 👉 《剑指Offer》全解析 Java 版
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如:输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
}
}
思路:
前序遍历:根左右。
中序遍历:左根右。
因为题目说了没有重复的数字
那么,
前序遍历里的 第一个数字 就是根结点,
这个数字 将 中序遍历 分成左右两边,
左边 就是左子树,右边 就是右子树。
然后,左子树 和 右子树 里,又分别重复上述操作。
就能还原出完整的二叉树了。
用案例说明思路:
前序序列{1,2,4,7,3,5,6,8} = pre
中序序列{4,7,2,1,5,3,8,6} = in
- 根据 前序序列 的第一个结点 确定根结点,为 1
- 找到 1 在 中 序序列 中的位置,为 in[3]
- 用这个切割 左 右子树,则中序序列中 in[3] 前面的为左子树 {4,7,2}, in[3] 后面的为右子树 {5,3,8,6 }
- 则切割后的左子树前序序列为:{2,4,7},切割后的左子树中序序列为:{4,7,2};
切割后的右子树前序序列为:{3,5,6,8},切割后的右子树中序序列为:{5,3,8,6} - 对左右子树分别重复使用上面的方法分解
- 最后就能还原整个二叉树了
用算法的话,那就是用递归来了~
实现1:
先了解一个 Arrays.copyOfRange 方法
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
import java.util.*;
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre.length == 0 || in.length == 0){
return null;
}
TreeNode node = new TreeNode(pre[0]);
for(int i=0; i < in.length; i++){
if(pre[0] == in[i]){
node.left = reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
node.right = reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
}
}
return node;
}
}
实现2,不用 Arrays.copyOfRange 方法,自己实现新数组存储:
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
TreeNode root = reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
return root;
}
private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in, int startIn,int endIn){
if(startPre > endPre || startIn > endIn)
return null;
TreeNode root = new TreeNode(pre[startPre]);
for(int i = startIn; i <= endIn; i++ )
if(in[i] == pre[startPre]){
root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
break;
}
return root;
}
}
看完之后,如果还有什么不懂的,可以在评论区留言,会及时回答更新。
这里是猿兄,为你分享程序员的世界。
非常感谢各位大佬们能看到这里,如果觉得文章还不错的话, 求点赞👍 求关注💗 求分享👬求评论📝 这些对猿兄来说真的 非常有用!!!
注: 如果猿兄这篇博客有任何错误和建议,欢迎大家留言,不胜感激!