二叉树入门
题目目录
- 二叉树入门
- 还原二叉树
- 根据前序中序还原二叉树
- 根据中序后序还原二叉树
- 树的搜索
- 深度优先
- 广度优先
- 树的比较
- 完全相等 才算通过
- 左右子树互换也算相等
二叉树的存储方式,如何根据存储方式还原二叉树,热门题目
- 存前序和中序
- 存后续和中序
还原二叉树
根据前序中序还原二叉树
找特点
区别 :
- 前序的根节点在 第一位,中序的根节点在中间
- 只要找到左子树的数量,右子树也可以随之实现
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;
}
代码语言:javascript复制效率版
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;
}
代码语言:javascript复制效率版
// 存储 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;
}
树的搜索
深度优先
就是有限向下来搜索,
二叉树深度优先的代码也非常的好理解
代码语言:javascript复制 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);
}
广度优先
按照一层一层的找吗,有限寻找同一层的
代码
判断是否存在的
代码语言:javascript复制 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);
}
第二种解法
返回输出集合的
代码语言:javascript复制 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;
}
树的比较
完全相等 才算通过
很简单的递归思路,
代码语言:javascript复制 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的左右子树分别比较即可
代码语言:javascript复制 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);
}