1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public int minTime(int n, int[][] edges, List<Boolean> hasApple) {
Map<Integer, List<Integer>> nodeNeighbors = new HashMap<>();
for (int[] edge : edges) {
nodeNeighbors.computeIfAbsent(edge[0], (key) -> new ArrayList<>()).add(edge[1]);
nodeNeighbors.computeIfAbsent(edge[1], (key) -> new ArrayList<>()).add(edge[0]);
}
int path = dfs(0, nodeNeighbors, hasApple, new HashSet<>());
return path == 0 ? path : path - 2;
}

private int dfs(int currNode, Map<Integer, List<Integer>> nodeNeighbors, List<Boolean> hasApple,
Set<Integer> visited) {
visited.add(currNode);
int path = 0;
for (int neighbor : nodeNeighbors.get(currNode)) {
if (!visited.contains(neighbor)) {
int subtreePath = dfs(neighbor, nodeNeighbors, hasApple, visited);
path += subtreePath;

}
}
if (hasApple.get(currNode) || path != 0) {
path += 2;
}
visited.remove(currNode);
return path;
}
}

递归函数的作用就是告诉我们从当前node出发把左或者右树中的apple摘取完需要的path是多少.这里把subtree的苹果摘完返回到subtree的root不算完还要返回该root的parent, 等于是从parent就开始记录然后再回到parent需要的步数.

如果一个subtree中没有苹果, 那么返回0, 否则返回一个正数. 因此我们在main函数中调用该递归函数时需要判断返回的值, 如果是0, 那就说明给的树中没有苹果, 返回0即可; 如果大于0, 我们要手动-2, 因为所在的main函数等效于我们在一个parent node中向root调用, 因此要减去2.

时间复杂度: O(n)
空间复杂度: O(n)