多叉树题目:子树中标签相同的结点数

文章目录

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

题目

标题和出处

标题:子树中标签相同的结点数

出处:1519. 子树中标签相同的结点数

难度

5 级

题目描述

要求

给你一个树(即一个连通的无向无环图),这个树由编号从 0 \texttt{0} 0 n − 1 \texttt{n} - \texttt{1} n1 n \texttt{n} n 个结点和 n − 1 \texttt{n} - \texttt{1} n1 条边 edges \texttt{edges} edges 组成。树的根结点为结点 0 \texttt{0} 0,树中的每一个结点都有一个标签,标签是字符串 labels \texttt{labels} labels 中的一个小写字符(编号为 i \texttt{i} i 的结点的标签是 labels[i] \texttt{labels[i]} labels[i])。

边数组 edges \texttt{edges} edges edges[i] = [a i , b i ] \texttt{edges[i] = [a}_\texttt{i}\texttt{, b}_\texttt{i}\texttt{]} edges[i] = [ai, bi] 的形式给出,该格式表示结点 a i \texttt{a}_\texttt{i} ai b i \texttt{b}_\texttt{i} bi 之间存在一条边。

返回一个大小为 n \texttt{n} n 的数组 ans \texttt{ans} ans,其中 ans[i] \texttt{ans[i]} ans[i] 表示第 i \texttt{i} i 个结点的子树中与结点 i \texttt{i} i 标签相同的结点数。

T \texttt{T} T 的子树是由 T \texttt{T} T 中的某个结点及其所有后代结点组成的树。

示例

示例 1:

示例 1

输入: n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], labels = "abaedcd" \texttt{n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], labels = "abaedcd"} n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], labels = "abaedcd"
输出: [2,1,1,1,1,1,1] \texttt{[2,1,1,1,1,1,1]} [2,1,1,1,1,1,1]
解释:结点 0 \texttt{0} 0 的标签为 ‘a’ \texttt{`a'} ‘a’ ,以 ‘a’ \texttt{`a'} ‘a’ 为根结点的子树中,结点 2 \texttt{2} 2 的标签也是 ‘a’ \texttt{`a'} ‘a’,因此答案为 2 \texttt{2} 2。注意树中的每个结点都是这个子树的一部分。
结点 1 \texttt{1} 1 的标签为 ‘b’ \texttt{`b'} ‘b’,结点 1 \texttt{1} 1 的子树包含结点 1 \texttt{1} 1 4 \texttt{4} 4 5 \texttt{5} 5,由于结点 4 \texttt{4} 4 5 \texttt{5} 5 的标签与结点 1 \texttt{1} 1 不同,因此答案为 1 \texttt{1} 1(该结点本身)。

示例 2:

示例 2

输入: n = 4, edges = [[0,1],[1,2],[0,3]], labels = "bbbb" \texttt{n = 4, edges = [[0,1],[1,2],[0,3]], labels = "bbbb"} n = 4, edges = [[0,1],[1,2],[0,3]], labels = "bbbb"
输出: [4,2,1,1] \texttt{[4,2,1,1]} [4,2,1,1]
解释:结点 2 \texttt{2} 2 的子树中只有结点 2 \texttt{2} 2,因此答案为 1 \texttt{1} 1
结点 3 \texttt{3} 3 的子树中只有结点 3 \texttt{3} 3,因此答案为 1 \texttt{1} 1
结点 1 \texttt{1} 1 的子树中包含结点 1 \texttt{1} 1 2 \texttt{2} 2,标签都是 ‘b’ \texttt{`b'} ‘b’,因此答案为 2 \texttt{2} 2
结点 0 \texttt{0} 0 的子树中包含结点 0 \texttt{0} 0 1 \texttt{1} 1 2 \texttt{2} 2 3 \texttt{3} 3,标签都是 ‘b’ \texttt{`b'} ‘b’,因此答案为 4 \texttt{4} 4

示例 3:

示例 3

输入: n = 5, edges = [[0,1],[0,2],[1,3],[0,4]], labels = "aabab" \texttt{n = 5, edges = [[0,1],[0,2],[1,3],[0,4]], labels = "aabab"} n = 5, edges = [[0,1],[0,2],[1,3],[0,4]], labels = "aabab"
输出: [3,2,1,1,1] \texttt{[3,2,1,1,1]} [3,2,1,1,1]

数据范围

  • 1 ≤ n ≤ 10 5 \texttt{1} \le \texttt{n} \le \texttt{10}^\texttt{5} 1n105
  • edges.length = n − 1 \texttt{edges.length} = \texttt{n} - \texttt{1} edges.length=n1
  • edges[i].length = 2 \texttt{edges[i].length} = \texttt{2} edges[i].length=2
  • 0 ≤ a i , b i < n \texttt{0} \le \texttt{a}_\texttt{i}\texttt{, b}_\texttt{i} < \texttt{n} 0ai, bi<n
  • a i ≠ b i \texttt{a}_\texttt{i} \ne \texttt{b}_\texttt{i} ai=bi
  • labels.length = n \texttt{labels.length} = \texttt{n} labels.length=n
  • labels \texttt{labels} labels 仅由小写英语字母组成

解法

思路和算法

这道题中的树是一个无向无环的连通图,规定根结点是结点 0 0 0,其余结点之间只能知道连通关系。为了得到相邻结点之间的父结点和子结点的关系,需要根据给定的边得到每个结点的相邻结点,然后从根结点开始遍历树。在确定所有相邻结点之间的父结点和子结点的关系之后,即可得到每个子树中包含的结点。对于每个子树,遍历子树中的每个结点即可得到与子树根结点标签相同的结点数。

由于树中的结点数 n n n 最大可达 1 0 5 10^5 105,因此应该尽量避免重复访问结点,而是每个结点都访问一次。由于树中的每个标签的出现次数由树的根结点标签与每个子树中的每个标签的出现次数决定,因此可以使用后序遍历的方式得到每个子树中的每个标签的出现次数,然后得到每个子树中与子树根结点标签相同的结点数。

对于每个子树,需要使用哈希表记录子树中每个标签的出现次数。当子树中只有一个结点时,只有子树根结点的标签出现 1 1 1 次,其余标签都不出现;当子树的根结点有子结点时,将每个子结点对应的每个标签的出现次数加到子树根结点的每个标签的出现次数,最后将子树根结点的标签的出现次数加 1 1 1,即可得到子树中每个标签的出现次数。

实现方面有以下两点说明。

  1. 由于标签只包含小写英语字母,因此可以使用长度为 26 26 26 的数组代替哈希表记录每个标签的出现次数。

  2. 遍历过程中需要知道相邻结点之间的父结点和子结点的关系。由于和一个结点相邻的结点只有该结点的父结点和全部子结点,一种方法是在遍历过程中传入当前结点的父结点编号,在遍历与当前结点相邻的结点时跳过父结点,则可确保只会访问当前结点的子结点。

代码

class Solution {String labels;List<Integer>[] adjacentNodes;int[][] counts;public int[] countSubTrees(int n, int[][] edges, String labels) {this.labels = labels;adjacentNodes = new List[n];for (int i = 0; i < n; i++) {adjacentNodes[i] = new ArrayList<Integer>();}for (int[] edge : edges) {int node0 = edge[0], node1 = edge[1];adjacentNodes[node0].add(node1);adjacentNodes[node1].add(node0);}counts = new int[n][26];postorder(0, -1);int[] ans = new int[n];for (int i = 0; i < n; i++) {char c = labels.charAt(i);ans[i] = counts[i][c - 'a'];}return ans;}public void postorder(int node, int parent) {char c = labels.charAt(node);List<Integer> adjacent = adjacentNodes[node];for (int next : adjacent) {if (next == parent) {continue;}postorder(next, node);for (int i = 0; i < 26; i++) {counts[node][i] += counts[next][i];}}counts[node][c - 'a']++;}
}

复杂度分析

  • 时间复杂度: O ( n × ∣ Σ ∣ ) O(n \times |\Sigma|) O(n×∣Σ∣),其中 n n n 是树的结点数, Σ \Sigma Σ 是字符集,这道题中 Σ \Sigma Σ 是全部小写英语字母, ∣ Σ ∣ = 26 |\Sigma| = 26 ∣Σ∣=26。后序遍历需要访问每个结点一次,对于每个结点需要 O ( ∣ Σ ∣ ) O(|\Sigma|) O(∣Σ∣) 的时间计算以该结点为根结点的子树中的每个标签的出现次数。

  • 空间复杂度: O ( n × ∣ Σ ∣ ) O(n \times |\Sigma|) O(n×∣Σ∣),其中 n n n 是树的结点数, Σ \Sigma Σ 是字符集,这道题中 Σ \Sigma Σ 是全部小写英语字母, ∣ Σ ∣ = 26 |\Sigma| = 26 ∣Σ∣=26。空间复杂度包括存储相邻结点信息的空间、哈希表空间和递归调用的栈空间,存储相邻结点信息的空间是 O ( n ) O(n) O(n),哈希表空间是 O ( n × ∣ Σ ∣ ) O(n \times |\Sigma|) O(n×∣Σ∣),即每个结点需要 O ( ∣ Σ ∣ ) O(|\Sigma|) O(∣Σ∣) 的空间记录以该结点为根结点的子树中的每个标签的出现次数,递归调用的栈空间在最坏情况下是 O ( n ) O(n) O(n),因此空间复杂度是 O ( n × ∣ Σ ∣ ) O(n \times |\Sigma|) O(n×∣Σ∣)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JDK下载及安装说明

1&#xff0e;JDK下载 访问oracle官网&#xff1a;http://www.oracle.com 在首页点击Downloads&#xff0c;进入oracle软件下载页。 在下载页面&#xff0c;点击Java。 选择Java (JDK) for Developers&#xff0c;点击。 在 Java SE Downloads 页面&#xff0c;点击中间的DO…

app上架-您的应用存在最近任务列表隐藏风险活动的行为,不符合华为应用市场审核标准。

上架提示 您的应用存在最近任务列表隐藏风险活动的行为&#xff0c;不符合华为应用市场审核标准。 修改建议&#xff1a;请参考测试结果进行修改。 请参考《审核指南》第2.19相关审核要求&#xff1a;https://developer.huawei.com/consumer/cn/doc/app/50104-02 造成原因 …

后端说处理了跨域但没有生效

场景&#xff1a; 常见的跨域报错&#xff0c;一般都是由后端进行setHeader/*什么的。但是现在这种情况就是后端说他们做了处理。但是我这边请求还是报错。 withCredentials: with-credentials用来设置是否发送cookie&#xff0c;如果为true就会在跨域请求时候携带cookie&…

libVLC 提取视频帧

在前面的文章中&#xff0c;我们使用libvlc_media_player_set_hwnd设置了视频的显示的窗口。 libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow->winId()); 如果我们想要提取每一帧数据&#xff0c;将数据保存到本地&#xff0c;该如何操作呢&#x…

Golang 开发实战day09 - package Scope

&#x1f3c6;个人专栏 &#x1f93a; leetcode &#x1f9d7; Leetcode Prime &#x1f3c7; Golang20天教程 &#x1f6b4;‍♂️ Java问题收集园地 &#x1f334; 成长感悟 欢迎大家观看&#xff0c;不执着于追求顶峰&#xff0c;只享受探索过程 Golang 教程09 - package Sc…

算法练习第12天|● 239. 滑动窗口最大值● 347.前 K 个高频元素

239.滑动窗口的最大值 力扣原题 题目描述&#xff1a; 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1&#xff…

影响力营销与AI的结合:Kompas.ai在搭桥角色中的独特价值

在数字化营销的新时代&#xff0c;影响力营销已经成为品牌建立信任和提升市场影响力的有效手段。通过与关键意见领袖&#xff08;KOL&#xff09;的合作&#xff0c;品牌能够利用KOL的信誉和影响力来扩大其市场覆盖范围和提升品牌认知度。然而&#xff0c;寻找与品牌价值观相契…

Linux 性能分析工具大全

vmstat--虚拟内存统计 vmstat&#xff08;VirtualMeomoryStatistics&#xff0c;虚拟内存统计&#xff09;是 Linux 中监控内存的常用工具,可对操作系统的虚拟内存、进程、CPU 等的整体情况进行监视。vmstat 的常规用法&#xff1a;vmstat interval times 即每隔 interval 秒采…

rsync+inotify实时同步 和 GFS分布式文件系统概述

目录 一、rsyncinotify实时同步 1.1.实时同步的优点 1.2.Linux内核的inotify机制 1.3.发起端配置rsyncInotify 1.4.配置远程登陆 1.4.1.修改rsync源服务器配置192.168.190.101 ​编辑 1.4.2.配置server 192.168.190.102 二、GFS 2.1.GlusterFS简介 2.2.GlusterFS特点…

Flutter学习11 - Future 与 FutureBuilder

1、Future 可以利用 Future 实现异步调用 1.1、Future 的两种形式 自定义一个结果类 class Response {String _data;Response(this._data); }自定义方法实现 Future Future<Response> testFuture() {var random Random();int randomNumber random.nextInt(10);if …

DIY自己的AI

一、开源AI大语言模型 目前开源的AI大语言模型(LLM)已经非常的多了&#xff0c;以下是收集的一些LLM&#xff1a; LLaMA LLaMA&#xff08;Large Language Model Meta AI&#xff09;&#xff1a;LLaMA是由MetaAI的Facebook人工智能实验室&#xff08;FAIR&#xff09;发布的…

大鼠尾静脉注射仪和小鼠尾静脉注射仪的区别

ZL-02B大鼠可视尾静脉注射仪是用于大鼠尾注射的一款仪器&#xff0c;以往给大鼠注射都是靠盲打&#xff0c;靠经验&#xff0c;对科研新手来说极其困难&#xff0c;有了大鼠尾静脉注射仪&#xff0c;可以大大提高注射效率&#xff0c;该仪器可以显示出尾部血管位置&#xff0c;…

Jenkins 持续集成 【CICD】

持续集成 &#xff08;Continuous integration&#xff0c;简称CI&#xff09; 持续集成是一种开发实践&#xff0c;它倡导团队成员频繁的集成他们的工作&#xff0c;每次集成都通过自动化构建&#xff08;包括编译、构建、打包、部署、自动化测试&#xff09;来验证&#xff…

python实现OCR:pytesseract和pyddleocr(附代码)

文章目录 背景pytesseractpaddleocr百度apipaddleocr 背景 OCR是光学字符识别&#xff08;Optical Character Recognition&#xff09;的缩写&#xff0c;通过扫描等光学输入方式和文字识别将图片中的文字提取出来&#xff0c;非常适用于提取网络截图或扫描pdf等文件里的文本。…

成都欣丰洪泰文化传媒有限公司电商服务的新锐力量

在当今电商行业风起云涌的时代&#xff0c;成都欣丰洪泰文化传媒有限公司以其独特的视角和专业的服务&#xff0c;成为了业内的佼佼者。该公司专注于电商服务&#xff0c;致力于为广大商家提供全方位、多层次的解决方案&#xff0c;助力商家在激烈的市场竞争中脱颖而出。 一、…

使用 Python 批量提取 Excel 中的图片(提供工具下载链接)

本文收录于《Python入门核心技术》专栏&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 大家好&#xff0c;我是水滴~~ 本文主要讲解如何利用 Python 来批量提取 Excel 中的图片&#xff0c;分别保存到目录中。并将程序打包成可执行文件&am…

rsync+inotify组合实现及时远程同步

目录 Rsync&#xff08;Remote Sync&#xff09;简介&#xff1a; Rsync 主要特点&#xff1a; Rsync 常用命令选项&#xff1a; Inotify 简介&#xff1a; Inotify 的主要功能&#xff1a; 结合 Rsync 和 Inotify 实现实时同步&#xff1a; 操作步骤&#xff1a; 配置…

vue3前端加载动画 lottie-web 的简单使用案例

什么是 Lottie Lottie 是 Airbnb 发布的一款开源动画库&#xff0c;它适用于 Android、iOS、Web 和 Windows 的库。 它提供了一套从设计师使用 AE&#xff08;Adobe After Effects&#xff09;到各端开发者实现动画的工具流。 UED 提供动画 json 文件即可&#xff0c; 开发者就…

品牌发言稿怎么写?纯干货

品牌发言稿的重要性不言而喻&#xff0c;它不仅代表着品牌形象&#xff0c;更是沟通品牌与消费者、合作伙伴的桥梁。如何撰写一篇高质量的品牌发言稿&#xff0c;成为许多品牌关注的焦点。伯乐网络传媒十多年文案撰写经验&#xff0c;今天就来给大家讲一讲。 一、品牌发言稿的组…

跨服务器迁移nextcloud数据

背景 阿里云最近做活动,99一年的2U2G的服务器,比我原来的1U1G的服务器不知道高到哪里去了,于是决定迁移服务器数据到另一台主机上。原先的计划是直接做一个自定义镜像,然后复制到另一台主机就行,结果发现旧主机是aliyunOS,新主机不想踩这个坑了,决定换成乌班图,因此决定重新搭…