六道入门树题目带你走入树结构的世界-liu-dao-ru-men-shu-ti-mu-dai-ni-zou-ru-shu-jie-gou-de-shi-jie

简介: 六道入门树题目带你走入树结构的世界-liu-dao-ru-men-shu-ti-mu-dai-ni-zou-ru-shu-jie-gou-de-shi-jie

二叉树入门

二叉树的存储方式,如何根据存储方式还原二叉树,热门题目

  1. 存前序和中序
  2. 存后续和中序

还原二叉树

根据前序中序还原二叉树

找特点

区别 :

  • 前序的根节点在 第一位,中序的根节点在中间
  • 只要找到左子树的数量,右子树也可以随之实现
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);
    }
目录
相关文章
|
Kubernetes 搜索推荐 应用服务中间件
【kubernetes】新版helm3的三大概念+快速指南+自定义charts模板
chart:代表helm包,包含在 Kubernetes 集群内部运行应用程序,工具或服务所需的所有资源定义。 Repository(仓库):用来存放和共享 charts 的地方。 Release :运行在 Kubernetes 集群中的 chart 的实例,一个 chart 通常可以在同一个集群中安装多次,每一次安装都会创建一个新的 release。
730 1
【kubernetes】新版helm3的三大概念+快速指南+自定义charts模板
|
机器学习/深度学习 传感器 人工智能
AI与环境保护:可持续发展的伙伴
在科技日新月异的时代,人工智能(AI)不仅改变了我们的生活和工作方式,还在环保和可持续发展领域发挥重要作用。AI通过环境监测、资源优化、垃圾分类、绿色出行和环保教育等多方面的应用,为环保事业注入新活力,推动社会向更加绿色、可持续的方向发展。
|
运维 Kubernetes Cloud Native
还在为多集群管理烦恼吗?OCM来啦!
在云计算领域如果还有人没听过 Kubernetes,就好像有人不知道重庆火锅必须有辣椒。Kubernetes 已经像手机上的 Android,笔记本上的 Windows 一样成为管理数据中心事实上的标准平台了。围绕着 Kubernetes,开源社区构建了丰富的技术生态,无论是 CI/CD、监控运维,还是应用框架、安全反入侵,用户都能找到适合自己的项目和产品。可是,一旦将场景扩展到多集群、混合云环境时,用户能够依赖的开源技术就屈指可数,而且往往都不够成熟、全面。
还在为多集群管理烦恼吗?OCM来啦!
|
人工智能 搜索推荐 机器人
神奇智能搜索引擎:perplexity智能搜索引擎(ChatGPT与Edge合体——联网版chatGPT)
神奇智能搜索引擎:perplexity智能搜索引擎(ChatGPT与Edge合体——联网版chatGPT)
|
消息中间件 监控 前端开发
我有 7种 实现web实时消息推送的方案,7种!
我有 7种 实现web实时消息推送的方案,7种!
3939 2
我有 7种 实现web实时消息推送的方案,7种!
|
机器学习/深度学习 人工智能 编解码
关于AI 绘画,我给你总结了一份详细的关键词(Prompt 知识)
AI绘画是利用人工智能技术进行图像生成和图像编辑的过程。它主要包括两个方面,一个是基于机器学习的图像生成,另一个是基于计算机视觉技术的图像编辑。
1754 0
关于AI 绘画,我给你总结了一份详细的关键词(Prompt 知识)
|
弹性计算 对象存储 CDN
阿里云账号注册流程(2023新版教程)
阿里云账号怎么注册?可以使用手机注册、支付宝或钉钉注册均可以,阿里云账号怎么注册?阿里云账号支持手机号注册、阿里云APP注册、支付宝和钉钉多种注册方式,账号注册后需要通过实名认证才可以购买或使用云产品,阿里云百科来详细说下不同途径注册阿里云账号图文流程:
1900 0
阿里云账号注册流程(2023新版教程)
|
JavaScript 前端开发 定位技术
最佳网络地图服务对比分析:Google Maps 与 OpenStreetMap
最佳网络地图服务对比分析:Google Maps 与 OpenStreetMap
974 0
最佳网络地图服务对比分析:Google Maps 与 OpenStreetMap
|
弹性计算 容灾 安全
阿里云服务器购买指南(超详细)
阿里云服务器购买指南(超详细)2023阿里云服务器选购流程更新,选购云服务器有两个入口,一个是选择活动机,只需要选择云服务器地域、系统、带宽即可;另一个是在云服务器页面,自定义选择云服务器配置,这种方式购买云服务器较为复杂,需要选付费方式、地域及可用区、ECS实例规格、镜像、网络、公网IP、安全组等配置,阿里云百科来阿里云服务器购买流程指南2023新版教程:
787 0
|
分布式计算 资源调度 关系型数据库
数据实时同步平台搭建
数据实时同步平台搭建