题目24:1443. 收集树上所有苹果的最少时间
同类题目
前置知识
- 无
题目描述
-
给你一棵有
n
个节点的无向树,节点编号为0
到n-1
,它们中有一些节点有苹果。通过树上的一条边,需要花费 1 秒钟。你从 节点 0 出发,请你返回最少需要多少秒,可以收集到所有苹果,并回到节点 0 。无向树的边由
edges
给出,其中edges[i] = [fromi, toi]
,表示有一条边连接from
和toi
。除此以外,还有一个布尔数组hasApple
,其中hasApple[i] = true
代表节点i
有一个苹果,否则,节点i
没有苹果。示例 1:
输入:n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,true,true,false] 输出:8 解释:上图展示了给定的树,其中红色节点表示有苹果。一个能收集到所有苹果的最优方案由绿色箭头表示。
示例 2:
输入:n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,false,true,false] 输出: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] 输出:0
提示:
1 <= n <= 10^5
edges.length == n - 1
edges[i].length == 2
0 <= ai < bi <= n - 1
hasApple.length == n
思路分析
子问题+从低往上
对于树中的每一个节点,计算收集所有该节点的所有子节点的苹果耗时
- 图的存储使用邻接表
- 对于树中每个节点,返回收集该节点子树中所有苹果需要的时间
- 返回收集完当前子树的所有的苹果的总的时间
自底向上计算耗时,由于每一条边必定要走两遍,因此如果子树有苹果,那么为了返回到当前节点,这条边必走两遍,耗时为2。
每一棵树总耗时 = 所有子树耗时 + 当前节点耗时
程序代码
方法一:
//https://leetcode.cn/problems/minimum-time-to-collect-all-apples-in-a-tree/description/
// 1443. 收集树上所有苹果的最少时间
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
int dfs(vector<vector<int>>& graph, vector<bool>& visited, vector<bool>& hasApple, int node, int mycost) {
if ( visited[node] ) {
return 0;
}
visited[node] = true;
// 计算子树的耗时
int child_cost = 0;
for ( int child : graph[node] ) {
// 计算子树的耗时
child_cost += dfs(graph, visited, hasApple, child, 2);
}
// 如果当前节点的子树没有苹果并且当前节点也没有苹果,那么当前节点的子树无需遍历,耗时为0
if ( child_cost == 0 && !hasApple[node] ) {
return 0;
}
// 当前节点子树的总耗时 = 子树耗时 + 当前节点的耗时
return child_cost + mycost;
}
int minTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {
// 建图
vector<vector<int>> graph(n, vector<int>());
for ( const auto& edge : edges ) {
graph[edge[0]].push_back(edge[1]);
graph[edge[1]].push_back(edge[0]);
}
// 记录该节点是否已经访问
vector<bool> visited(n, false);
return dfs(graph, visited, hasApple, 0, 0);
}
};
复杂度分析
时间复杂度:O(N)
,一共有 N
个节点,每个节点都需要遍历一次。
空间复杂度:O(N)
,主要是数组的开销。
题目感悟
更多相关知识:github.com/pingguo1987…