二叉树题目:具有所有最深结点的最小子树

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法一
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法二
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:具有所有最深结点的最小子树

出处:865. 具有所有最深结点的最小子树

难度

5 级

题目描述

要求

给定二叉树的根结点 root \texttt{root} root,每个结点的深度是该结点到根的最短距离

返回包含原始树中所有最深结点的最小子树。

如果一个结点在整个树的所有结点中具有最大的深度,则该结点是最深的

一个结点的子树是该结点加上它的所有后代的集合。

示例

示例 1:

示例 1

输入: root   =   [3,5,1,6,2,0,8,null,null,7,4] \texttt{root = [3,5,1,6,2,0,8,null,null,7,4]} root = [3,5,1,6,2,0,8,null,null,7,4]
输出: [2,7,4] \texttt{[2,7,4]} [2,7,4]
解释:
我们返回值为 2 \texttt{2} 2 的结点,在图中用黄色标记。
在图中用蓝色标记的是树的最深的结点。
注意,结点 5 \texttt{5} 5 3 \texttt{3} 3 2 \texttt{2} 2 包含树中最深的结点,但结点 2 \texttt{2} 2 的子树最小,因此我们返回它。

示例 2:

输入: root   =   [1] \texttt{root = [1]} root = [1]
输出: [1] \texttt{[1]} [1]
解释:根结点是树中最深的结点。

示例 3:

输入: root   =   [0,1,3,null,2] \texttt{root = [0,1,3,null,2]} root = [0,1,3,null,2]
输出: [2] \texttt{[2]} [2]
解释:树中最深的结点为 2 \texttt{2} 2,有效子树为结点 2 \texttt{2} 2 1 \texttt{1} 1 0 \texttt{0} 0 的子树,但结点 2 \texttt{2} 2 的子树最小。

数据范围

  • 树中结点数目在范围 [1,   500] \texttt{[1, 500]} [1, 500]
  • 0 ≤ Node.val ≤ 500 \texttt{0} \le \texttt{Node.val} \le \texttt{500} 0Node.val500
  • 树中的所有值各不相同

解法一

思路和算法

由于所有最深结点的深度相同,因此对于包含所有最深结点的子树,每个最深结点到子树根结点的距离相同。只要定位到所有最深结点,即可找到包含所有最深结点的最小子树的根结点。

为了定位到所有最深结点,可以使用层序遍历。从根结点开始依次遍历每一层的结点,在层序遍历的过程中需要区分不同结点所在的层,确保每一轮访问的结点为同一层的全部结点。遍历每一层结点之前首先得到当前层的结点数,即可确保每一轮访问的结点为同一层的全部结点。层序遍历访问的最后一层结点即为所有最深结点。

定位到所有最深结点之后,从最深结点向根结点移动,即每次从当前结点移动到父结点。由于每个最深结点到子树根结点的距离相同,因此每个最深结点将同时移动到包含所有最深结点的最小子树的根结点。使用哈希集合存储每次移动之后的结点集合,每次移动之后,结点数量一定不变或减少,当只剩下一个结点时,该结点即为包含所有最深结点的最小子树的根结点。

代码

class Solution {
    public TreeNode subtreeWithAllDeepest(TreeNode root) {
        Map<TreeNode, TreeNode> parentMap = new HashMap<TreeNode, TreeNode>();
        List<TreeNode> deepest = new ArrayList<TreeNode>();
        Queue<TreeNode> queue = new ArrayDeque<TreeNode>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            deepest.clear();
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                deepest.add(node);
                TreeNode left = node.left, right = node.right;
                if (left != null) {
                    parentMap.put(left, node);
                    queue.offer(left);
                }
                if (right != null) {
                    parentMap.put(right, node);
                    queue.offer(right);
                }
            }
        }
        Set<TreeNode> nodes = new HashSet<TreeNode>(deepest);
        while (nodes.size() > 1) {
            Set<TreeNode> parents = new HashSet<TreeNode>();
            for (TreeNode node : nodes) {
                parents.add(parentMap.get(node));
            }
            nodes = parents;
        }
        return nodes.iterator().next();
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。层序遍历访问每个结点一次,需要 O ( n ) O(n) O(n) 的时间,从所有最深结点移动到包含所有最深结点的最小子树的根结点的时间不超过 O ( n ) O(n) O(n),因此总时间复杂度是 O ( n ) O(n) O(n)

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是队列空间和哈希集合,队列内元素个数不超过 n n n,哈希集合内元素个数不超过 n n n

解法二

思路和算法

对于二叉树中的每个结点,考虑其左子树和右子树的深度。如果左子树和右子树的深度相同,则左子树和右子树中都有最深结点,当前结点就是包含所有最深结点的最小子树的根结点;如果左子树和右子树的深度不同,则所有最深结点一定在深度较大的子树中,需要在深度较大的子树中寻找包含所有最深结点的最小子树的根结点。因此,寻找包含所有最深结点的最小子树的根结点,等价于寻找左子树和右子树的深度相同的结点,以下将该结点称为「目标结点」。

从根结点开始深度优先搜索,计算每个子树的深度,并寻找目标结点。定义空树的深度为 0 0 0,当子树非空时,子树的深度为左子树的深度和右子树的深度中的最大值加 1 1 1

寻找目标结点的具体做法如下。

  1. 如果当前结点的左子树的深度和右子树的深度相同,则当前结点即为目标结点,当前子树的深度为左子树的深度加 1 1 1

  2. 否则,在深度较大的子树中寻找目标结点,当前子树的深度为深度较大的子树的深度加 1 1 1

上述过程是一个递归的过程,递归的终止条件是当前结点为空或者当前结点的左子树的深度和右子树的深度相同,其余情况则调用递归。

对于每个结点,首先访问其子结点寻找目标结点和计算子树高度,然后根据访问子结点的结果得到当前结点的结果。计算结果的顺序是先计算子结点的结果,后计算当前结点的结果,该顺序实质是后序遍历。由于在计算每个结点的结果时,该结点的子结点的结果已知,该结点的结果由子结点的结果决定,因此可以确保结果正确。

代码

class Solution {
    class NodeDepth {
        private TreeNode node;
        private int depth;

        public NodeDepth(TreeNode node, int depth) {
            this.node = node;
            this.depth = depth;
        }

        public TreeNode getNode() {
            return node;
        }

        public int getDepth() {
            return depth;
        }
    }

    public TreeNode subtreeWithAllDeepest(TreeNode root) {
        NodeDepth rootDepth = dfs(root);
        return rootDepth.getNode();
    }

    public NodeDepth dfs(TreeNode node) {
        if (node == null) {
            return new NodeDepth(node, 0);
        }
        NodeDepth left = dfs(node.left), right = dfs(node.right);
        TreeNode leftNode = left.getNode(), rightNode = right.getNode();
        int leftDepth = left.getDepth(), rightDepth = right.getDepth();
        if (leftDepth == rightDepth) {
            return new NodeDepth(node, leftDepth + 1);
        }
        return leftDepth > rightDepth ? new NodeDepth(leftNode, leftDepth + 1) : new NodeDepth(rightNode, rightDepth + 1);
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点都被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是深度优先搜索的过程中创建实例的空间和递归调用的栈空间,因此空间复杂度是 O ( n ) O(n) O(n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/181617.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【史上最细教程】一台服务器上搭建2个MySQL实例

史上最细教程-一台服务器上搭建2个MySQL实例 文章目录 史上最细教程-一台服务器上搭建2个MySQL实例环境准备&#xff1a;操作步骤&#xff1a;1.安装MySQL2.配置搭建3306、3307实例3.初始化3306、3307实例、远程连接访问支持 推荐文章&#xff1a; 环境准备&#xff1a; 服务器…

考过了PMP,面试的时候应该怎么办?

近期喜番在后台收到了很多同学们的私信&#xff0c;表示自己已经过了8月份的PMP考试&#xff0c;开始着手往项目管理岗位转型&#xff0c;但是对于项目管理岗位的面试却一筹莫展。放轻松&#xff0c;大家的需求喜番都了解了&#xff0c;喜番给大家总结了一些项目经理在面试的时…

护法革命:CIMIVO+SOTUY洗前发膜让发丝重获“芯”生

爱美之心人皆有之,经常烫染或者是在太阳下暴晒,都会对发丝造成一定的伤害,一旦发丝受损,就会导致发芯内部角蛋白流失、化学键连接断裂,进而出现各种发质问题。为此,日本知名化妆品集团NABOCUL旗下发芯修护引领品牌ENNEO创新研发两大核心成分:CIMIVO、SOTUY,能够从根源修护发芯内…

CLion安装与配置教程

目录 一、下载并安装CLion1、下载1、官网&#xff1a;2、注意&#xff1a; 2、安装1、下载完成后&#xff0c;直接点击安装包安装&#xff0c;即可。2、开始安装&#xff0c;然后下一步3、可以在此处自定义地址&#xff0c;然后下一步4、根据系统版本选择&#xff0c;然后下一步…

C#开发的OpenRA游戏之属性Selectable(9)

C#开发的OpenRA游戏之属性Selectable(9) 在游戏里,一个物品是否具有选中的能力,是通过添加属性Selectable来实现的。当一个物品不能被用户选取,那么就不要添加这个属性。 这个属性定义在下面这段描述里: ^Selectable: Selectable: SelectionDecorations: WithSpriteCon…

网络安全入门教程(非常详细)从零基础入门到精通

网络安全是一个庞大而不断发展的领域&#xff0c;它包含多个专业领域&#xff0c;如网络防御、网络攻击、数据加密等。介绍网络安全的基本概念、技术和工具&#xff0c;逐步深入&#xff0c;帮助您成为一名合格的网络安全从业人员。 一、网络安全基础知识 1.计算机基础知识 了解…

[点云分割] Clustering of Pointclouds into Supervoxels

介绍 “Clustering of Pointclouds into Supervoxels” 是一种点云数据聚类的方法&#xff0c;用于将点云数据分割成具有相似特征的超体素&#xff08;supervoxel&#xff09;。 超体素是一种在点云数据中表示连续区域的方法&#xff0c;类似于像素在图像中表示连续区域。超体…

vue + docxtemplater 导出 word 文档

一、痛点 word 导出 这种功能其实之前都是后端实现的&#xff0c;但最近有个项目没得后端。所以研究下前端导出。 ps&#xff1a; 前端还可以导出 pdf&#xff0c;但是其分页问题需要话精力去计算才可能实现&#xff0c;并且都不是很完善。可参考之前的文章&#xff1a;利用 h…

Peter算法小课堂—前缀和数组的应用

桶 相当于计数排序&#xff0c;看一个视频 桶排序 太戈编程1620题 算法解析 #include <bits/stdc.h> using namespace std; const int R11; int cnt[R];//cnt[t]代表第t天新增几人 int s[R];//s[]数组是cnt[]数组的前缀和数组 int n,t; int main(){cin>>n;for(…

意图交易:为用户思考,而不是让用户思考

意图叙事 在前不久&#xff0c;知名加密投资机构 Paradigm 的 CTO 、研究员 Georgios Konstantopoulos 曾在推特上对现有 ChainAsset 模式的糟糕且割裂的体验进行了吐槽&#xff0c;这也道出了很多链上用户的痛点。同时他也认为现有加密基建设施需要为用户思考&#xff0c;而不…

Nginx:简介、安装与部署

一、Nginx简介 Nginx是一个很好的高性能Web和反向大力服务器&#xff0c;它具有很多非常优越的特性&#xff1a;在高连接并发的情况下&#xff0c;Nginx是Apahe服务器的不错的替代品&#xff1a;Nginx在美国是虚拟主机生意选择的软件平台之一。能够支持50000个并发连接数的响应…

若依vue-修改标题和图标

因为我们拉下来的代码,图标和logo是若依的,这和我们需要做出来的效果有差别 这个时候就需要去对应的文件内去修改标题和图标 (主要就是这两个地方的图标和标题) 修改菜单里面的logo以及文字 修改文字 位置: src/layout/component/Sidebar/Logo.vue 此处的title文字是定义在…

plantUML学习与实战

背景 在日常工作或者生活中&#xff0c;使用交互图来描述想法&#xff0c;往往相对于文字来说&#xff0c;可读性更高&#xff0c;同时一定程度上可以提高沟通效率&#xff0c;但是苦于&#xff0c;不想对一堆控件拖拖拉拉&#xff0c;本人就是一个很讨厌画图&#xff0c;但是…

谈思生物医疗直播 | 利用类器官模型研究肺的发育与稳态

类器官是一种三维细胞培养物&#xff0c;其在细胞类型&#xff0c;空间结构及生理功能上能够模拟对应器官&#xff0c;从而提供一个高度生理相关的系统。自2009年小肠类器官首次建立至今&#xff0c;类器官研究已经延伸到多个组织系统&#xff0c;并成为当下生命科学领域最热门…

改善钢棒直线度检测可靠性 在线直线度测量仪替代人工检测

根据GB/T908-2019标准规定&#xff0c;钢棒的尺寸包括直径或边长、长度、弯曲度等。因此钢棒在生产中进行尺寸检测&#xff0c;保证成品符合规格&#xff0c;是降低废品率的重要一环。 有些钢棒的弯曲很明显&#xff0c;肉眼可看&#xff0c;但更有很多不明显的需要借助工具检测…

亿级流量架构服务降级

什么是服务降级 如果看过我前面对服务限流的分析,理解服务降级就很容易了,对于一个景区,平时随便进出,但是一到春节或者十一国庆这种情况客流量激增,那么景区会限制同时进去的人数,这叫限流,那么什么是服务降级呢? 简单来说就是,将一些不太重要的景区项目砍掉,平时就那么三五…

[PTQ]均匀量化和非均匀量化

均匀量化和非均匀量化 基本概念 量化出发点&#xff1a;使用整型数据类型代替浮点数据&#xff0c;从而节省存储空间同时加快推理速度。量化基本形式 均匀量化&#xff1a;浮点线性映射到定点整型上&#xff0c;可以根据scale/offset完成量化/反量化操作。非均匀量化 PowersO…

CentOS 7 使用cJSON 库

什么是JSON JSON是一种轻量级的数据交换格式&#xff0c;可读性强、编写简单。键值对组合编写规则&#xff0c;键名使用双引号包裹&#xff0c;冒号&#xff1a;分隔符后面紧跟着数值&#xff0c;有两种常用的数据类型是对象和数组。 对象&#xff1a;使用花括号{}包裹起来的…

怎么用 AI 来智能审核 PDF合同?5步搞定!

大家都知道审合同是一个比较耗费精力的过程,有没有更好的办法来智能审核PDF合同呢,今天就教大家一招,用AI来智能审核PDF合同。 在开始之前呢,我们要找到一款带AI功能的工具,我试用过擎盾智能合同审查、幂律智能等工具,感觉都不太理想,经过一段时间的摸索,我找到了一款比较适合…

【Linux】关系运算符、shell判断脚本执行时是否有传参、判断文件/文件夹是否存在、判断字符串是否相等、判断上个命令执行是否正常、判断字符串是否为空

&#x1f984; 个人主页——&#x1f390;个人主页 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; 感谢点赞和关注 &#xff0c;每天进步一点点&#xff01;加油&#xff01;&…
最新文章