二叉树的存储方式,如何根据存储方式还原二叉树,热门题目
找特点
区别 :
public static TreeNode buildTree(int[] qian, int[] zhong) {
if (qian == null || zhong == null || qian.length == 0 || zhong.length == 0 || qian.length != zhong.length) {
return null;
}
// 从前序遍历中找到根节点
TreeNode root = new TreeNode(qian[0]);
int rootindex = 0;
int rootval = root.val;
//从中序数组中找到 root
for (int i = 0; i < zhong.length; i++) {
if (zhong[i] == rootval) {
rootindex = i;
}
}
//找到左子树的前序和中序
int[] leftZhong = Arrays.copyOfRange(zhong, 0, rootindex);
int[] leftQian = Arrays.copyOfRange(qian, 1, rootindex + 1);
//找到右子树的前序和中序
int[] rightZhong = Arrays.copyOfRange(zhong, rootindex + 1, zhong.length);
int[] rightQian = Arrays.copyOfRange(qian, rootindex + 1, qian.length);
// 递归构建左右子树
TreeNode left = buildTree(leftQian, leftZhong);
TreeNode right = buildTree(rightQian, rightZhong);
// 给根节点添加左右子树
root.left = left;
root.right = right;
return root;
}
效率版
TreeNode build(int[] preorder, int preStart, int preEnd,
int[] inorder, int inStart, int inEnd) {
// root 节点对应的值就是前序遍历数组的第一个元素
int rootVal = preorder[preStart];
// rootVal 在中序遍历数组中的索引
int index = 0;
for (int i = inStart; i <= inEnd; i++) {
if (inorder[i] == rootVal) {
index = i;
break;
}
}
TreeNode root = new TreeNode(rootVal);
// 递归构造左右子树
root.left = build(preorder, preStart + 1, preStart + leftSize,
inorder, inStart, index - 1);
root.right = build(preorder, preStart + leftSize + 1, preEnd,
inorder, index + 1, inEnd);
return root;
}
找特点
区别 :
public static TreeNode buildTree(int[] zhong, int[] hou) {
if (hou == null || zhong == null || hou.length == 0 || zhong.length == 0 || hou.length != zhong.length) {
return null;
}
// 从后序遍历中找到根节点
TreeNode root = new TreeNode(hou[hou.length - 1]);
int rootindex = 0;
int rootval = root.val;
//从中序数组中找到 root
for (int i = 0; i < zhong.length; i++) {
if (zhong[i] == rootval) {
rootindex = i;
}
}
//找到左子树的中序和后序
int[] leftZhong = Arrays.copyOfRange(zhong, 0, rootindex);
int[] leftHou = Arrays.copyOfRange(hou, 0, rootindex);
//找到右子树的中序和后序
int[] rightZhong = Arrays.copyOfRange(zhong, rootindex + 1, zhong.length);
int[] rightHou = Arrays.copyOfRange(hou, rootindex, hou.length - 1);
// 递归构建左右子树
TreeNode left = buildTree(leftZhong, leftHou);
TreeNode right = buildTree(rightZhong, rightHou);
// 给根节点添加左右子树
root.left = left;
root.right = right;
return root;
}
效率版
// 存储 inorder 中值到索引的映射
HashMap<Integer, Integer> valToIndex = new HashMap<>();
TreeNode buildTree(int[] inorder, int[] postorder) {
for (int i = 0; i < inorder.length; i++) {
valToIndex.put(inorder[i], i);
}
return build(inorder, 0, inorder.length - 1,
postorder, 0, postorder.length - 1);
}
/*
build 函数的定义:
后序遍历数组为 postorder[postStart..postEnd],
中序遍历数组为 inorder[inStart..inEnd],
构造二叉树,返回该二叉树的根节点
*/
TreeNode build(int[] inorder, int inStart, int inEnd,
int[] postorder, int postStart, int postEnd) {
// root 节点对应的值就是后序遍历数组的最后一个元素
int rootVal = postorder[postEnd];
// rootVal 在中序遍历数组中的索引
int index = valToIndex.get(rootVal);
TreeNode root = new TreeNode(rootVal);
// 递归构造左右子树
root.left = build(preorder, ?, ?,
inorder, ?, ?);
root.right = build(preorder, ?, ?,
inorder, ?, ?);
return root;
}
就是有限向下来搜索,
二叉树深度优先的代码也非常的好理解
public static boolean dfs(TreeNode root, int target) {
if (root == null) {
return false;
}
if (root.val == target) {
return true;
}
return dfs(root.left, target) || dfs(root.right, target);
}
按照一层一层的找吗,有限寻找同一层的
代码
判断是否存在的
public static boolean bfs(ArrayList<TreeNode> roots, int target) {
System.out.println(roots.get(0).val);
if (roots == null || roots.size() == 0) {
return false;
}
ArrayList<TreeNode> childRoots = new ArrayList<>();
for (TreeNode temp : roots) {
if (temp.val == target) {
return true;
}
if (temp.left != null) {
childRoots.add(temp.left);
}
if (temp.right != null) {
childRoots.add(temp.right);
}
}
return bfs(childRoots, target);
}
public static boolean bfs(TreeNode root, int target) {
ArrayList<TreeNode> roots = new ArrayList<>();
roots.add(root);
return bfs(roots, target);
}
第二种解法
返回输出集合的
public static List<Integer> bfs(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<TreeNode>();
List<Integer> list = new LinkedList<Integer>();
if (root == null) {
return list;
}
queue.add(root);
while (!queue.isEmpty()) {
TreeNode t = queue.remove();
if (t.left != null) {
queue.add(t.left);
}
if (t.right != null) {
queue.add(t.right);
}
list.add(t.val);
}
return list;
}
很简单的递归思路,
public static boolean compareTree(TreeNode tree1, TreeNode tree2) {
if (tree1 == null && tree2 != null || tree1 != null && tree2 == null) {
return true;
}
if (tree1 == null || tree2 == null) {
return true;
}
if (tree1.val != tree2.val) {
return false;
}
return compareTree(tree1.left, tree2.left) && compareTree(tree1.right, tree2.right);
}
需要修改一些条件,只需要在返回结果加上一个或者条件,tree1和tree2的左右子树分别比较即可
public static boolean compareTree(TreeNode tree1, TreeNode tree2) {
if (tree1 == null && tree2 != null || tree1 != null && tree2 == null) {
return true;
}
if (tree1 == null || tree2 == null) {
return true;
}
if (tree1.val != tree2.val) {
return false;
}
return compareTree(tree1.left, tree2.left) && compareTree(tree1.right, tree2.right)
|| compareTree(tree1.left, tree2.right) && compareTree(tree1.right, tree2.left);
}