多叉树题目:收集树上所有苹果的最少时间

文章目录

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

题目

标题和出处

标题:收集树上所有苹果的最少时间

出处:1443. 收集树上所有苹果的最少时间

难度

6 级

题目描述

要求

给定一个有 n \texttt{n} n 个结点的无向树,结点编号为 0 \texttt{0} 0 n − 1 \texttt{n} - \texttt{1} n1,有一些结点有苹果。通过树上的一条边需要花费 1 \texttt{1} 1 秒钟。计算从结点 0 \texttt{0} 0 出发收集所有苹果并回到结点 0 \texttt{0} 0 的最少时间的秒数并返回。

无向树的边由 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。除此以外,还有一个布尔数组 hasApple \texttt{hasApple} hasApple,其中 hasApple[i] = true \texttt{hasApple[i] = true} hasApple[i] = true 表示结点 i \texttt{i} i 有一个苹果,否则结点 i \texttt{i} i 没有苹果。

示例

示例 1:

示例 1

输入: n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,true,true,false] \texttt{n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,true,true,false]} n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,true,true,false]
输出: 8 \texttt{8} 8
解释:上图展示了给定的树,其中红色结点表示有苹果。一个能收集到所有苹果的最优方案由绿色箭头表示。

示例 2:

示例 2

输入: n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,false,true,false] \texttt{n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,false,true,false]} n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,false,true,false]
输出: 6 \texttt{6} 6
解释:上图展示了给定的树,其中红色结点表示有苹果。一个能收集到所有苹果的最优方案由绿色箭头表示。

示例 3:

输入: n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,false,false,false,false,false] \texttt{n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,false,false,false,false,false]} n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,false,false,false,false,false]
输出: 0 \texttt{0} 0

数据范围

  • 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 ≤ from i , to i ≤ n − 1 \texttt{0} \le \texttt{from}_\texttt{i}\texttt{, to}_\texttt{i} \le \texttt{n} - \texttt{1} 0fromi, toin1
  • from i < to i \texttt{from}_\texttt{i} < \texttt{to}_\texttt{i} fromi<toi
  • hasApple.length = n \texttt{hasApple.length} = \texttt{n} hasApple.length=n

解法

思路和算法

这道题中的树使用无向边表示,规定根结点是结点 0 0 0,其余结点之间只能知道连通关系。为了得到相邻结点之间的父结点和子结点的关系,需要根据给定的边得到每个结点的相邻结点,然后从根结点开始遍历树。在确定所有相邻结点之间的父结点和子结点的关系之后,即可得到树的结构,包括每个结点的父结点和子结点,然后计算收集树上所有苹果的最少时间。

可以使用深度优先搜索得到树的结构。从根结点开始遍历,遍历过程中需要知道相邻结点之间的父结点和子结点的关系。由于和一个结点相邻的结点只有该结点的父结点和全部子结点,一种方法是在遍历过程中传入当前结点的父结点编号,在遍历与当前结点相邻的结点时跳过父结点,则可确保只会访问当前结点的子结点。

为了将收集苹果的时间降到最低,对于树中的每个苹果,应该考虑最短路径,即从根结点直接到达苹果所在结点的路径。当树中有多个苹果时,收集苹果的过程中应该避免重复路径,即同一条边最多在两个方向上各走一次。例如,示例 1 中收集树上所有苹果需要经过的边包括 [ 0 , 1 ] [0, 1] [0,1] [ 1 , 4 ] [1, 4] [1,4] [ 1 , 5 ] [1, 5] [1,5] [ 0 , 2 ] [0, 2] [0,2],共有 4 4 4 条边,最少时间的方案下每条边走 2 2 2 次,因此最少时间是 8 8 8

基于上述分析,为了计算最少时间,需要计算收集树上所有苹果需要经过的最少边数,将边数乘以 2 2 2 即为最少时间。

计算过程中,为了避免重复计算,需要记录每个结点是否访问过,初始时只有根结点 0 0 0 被访问过。对于每个有苹果的结点,从该结点出发向根结点移动,将经过的每个结点(包括该结点本身)的状态都设为被访问过,当遇到一个已经访问过的结点时结束当前结点的移动。如果遇到一个已经访问过的结点 x x x,则从结点 x x x 到根结点的路径上的所有边都已经访问过,因此不应重复访问。

对于全部有苹果的结点计算结束之后,即可得到收集树上所有苹果需要经过的最少边数。

实现方面,可以在计算边数的同时计算最少时间,对于遍历到的每条边,将时间加 2 2 2

代码

class Solution {List<Integer>[] adjacentNodes;int[] parents;boolean[] visited;public int minTime(int n, int[][] edges, List<Boolean> hasApple) {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);}parents = new int[n];Arrays.fill(parents, -1);dfs(0, -1);visited = new boolean[n];visited[0] = true;int time = 0;for (int i = 0; i < n; i++) {if (hasApple.get(i)) {time += getTime(i);}}return time;}public void dfs(int node, int parent) {List<Integer> adjacent = adjacentNodes[node];for (int next : adjacent) {if (next == parent) {continue;}parents[next] = node;dfs(next, node);}}public int getTime(int node) {int time = 0;while (!visited[node]) {visited[node] = true;node = parents[node];time += 2;}return time;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是树的结点数。深度优先搜索的过程中每个结点访问一次,计算最少时间的过程中每条边最多遍历一次,共有 n n n 个结点和 n − 1 n - 1 n1 条边,因此时间复杂度是 O ( n ) O(n) O(n)

  • 空间复杂度: 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)

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

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

相关文章

Linux系统启动过程详解

启动过程是指计算机从开机自检到操作系统完全加载的一系列动作。深入理解启动过程对于有效解决启动问题、提升系统性能以及高效管理系统的启动组件至关重要。例如&#xff0c;可以帮助我们识别和处理在启动过程中可能出现的诸如硬件故障、配置错误等问题。例如帮助我们个性化定…

计算机组成原理【CO】Ch4 指令系统

文章目录 考纲第四章 指令系统4.1 指令格式4.2 指令的寻址方式4.3 程序的机器级代码表示4.4 CISC和RISC的基本概念 【※】扩展码指令计算【※】指令系统【指令格式】【※】指令的寻址方式【※】指令的机器级代码表示x86汇编指令&#xff08;重点关注 intel 格式&#xff09;MIP…

Jmeter参数化的 4 种方式用法总结

参数化就是用变量代替数据的过程&#xff0c;总结参数化的4种方式&#xff1a; 1、用户自定义变量 用户自定义变更有两种方法&#xff1a; &#xff08;1&#xff09;在测试计划面板中的用户定义的变量设置 说明&#xff1a;在此用户定义的变量对所有测试计划都会生效 &…

如何通过Linux pciehp sysfs接口控制PCIe Slot电源状态?-3

pciehp sysfs接口电源控制与NVME驱动卸载的区别 从NVMe SSD设计本身而言&#xff0c;当通过pciehp sysfs接口对PCIe插槽执行Power Off操作时&#xff0c;由于NVMe SSD作为PCIe设备&#xff0c;其电源供应是直接依赖于所连接的PCIe插槽提供的。当插槽电源被关闭时&#xff0c;会…

#382. 工资计算系统(继承和派生)

水个文 代码如下&#xff1a; #include <cstdio> #include <cstdlib> #include <iostream> using namespace std;const double RATIO 0.01; const double SALARY_PER_YEAR 35; const double BASE_SALARY 1000;// class Employer{ public:int workAge, sa…

【多线程】单例模式 | 饿汉模式 | 懒汉模式 | 指令重排序问题

文章目录 单例模式一、单例模式1.饿汉模式2.懒汉模式&#xff08;单线程&#xff09;3.懒汉模式&#xff08;多线程&#xff09;改进 4.指令重排序1.概念2.question:3.解决方法4总结&#xff1a; 单例模式 一、单例模式 单例&#xff0c;就是单个实例 在有些场景中&#xff0c…

蓝色系UX/UI设计求职面试作品集模版figmasketchPPT可编辑源文件

页面数量: 20P 页面尺寸:1920*1080PX 交付格式&#xff1a;figma、sketch、PPT 赠送文件&#xff1a;24款高质量样机&#xff08;PSD格式&#xff09; 该作品集虽然只有20页&#xff0c;但可根据需求复制作品集里已有的页面作为模版来扩展您的设计项目 该作品集模版可编辑可修…

设计模式在芯片验证中的应用——策略

1. 策略模式 策略模式是一种行为设计模式&#xff0c; 它能让你定义一系列算法&#xff0c; 并将每种算法分别放入独立的类中&#xff0c; 以使算法的对象能够相互替换。 在RTL设计中可能包含了复杂的多个访问仲裁逻辑&#xff0c;使用了多种算法来确定访问内存优先级顺序&am…

【CMake】CMake从入门到实战系列(九)——CMake中的字符串处理指令和运算符

文章目录 一、字符串处理指令string基本语法参数含义 二、字符串运算符字符串比较字符串连接字符串替换字符串长度字符串截取字符串转换大小写字符串正则表达式匹配和替换字符串查找子字符串字符串中查找正则表达式匹配的内容字符串附加 三 、示例 一、字符串处理指令string 在…

【Git教程】(十)版本库之间的依赖 —— 项目与子模块之间的依赖、与子树之间的依赖 ~

Git教程 版本库之间的依赖 1️⃣ 与子模块之间的依赖2️⃣ 与子树之间的依赖&#x1f33e; 总结 在 Git 中&#xff0c;版本库是发行单位&#xff0c;代表的是一个版本&#xff0c;而分支或标签则只能被创建在版本库这个整体中。如果一个项目中包含了若干个子项目&#xff0c;…

【Java】图片处理工具ImageMagick简介及其在Java中的应用

ImageMagick是一款强大的图像处理软件&#xff0c;它可以用于创建、编辑、合并和转换图像。它支持超过200种图像格式&#xff0c;并且提供了丰富的功能&#xff0c;包括图像缩放、旋转、裁剪、加水印、添加特效等。ImageMagick还支持批量处理图像&#xff0c;可以通过命令行或者…

PUBG绝地求生加速器用哪个好 最新带来绝地求生好用的加速器推荐

PUBG绝地求生加速器用哪个好 最新带来绝地求生好用的加速器推荐 绝地求生作为一款非常流行的游戏&#xff0c;吸引了全球亿万玩家的关注。相信大部分玩家都曾经在游戏中遇到过卡顿掉帧以及无法连接服务器的情况&#xff0c;&#xff0c;这对于游戏体验来说是非常不好的。今天…