生物进化录
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 204 ms, 内存: 25.1 MB
/*
* 题目思路:
* 首先构建树形结构,并对其进行深度优先遍历。
* 我们需要记录每个节点的子节点,并确保我们始终以字典序最小的方式记录遍历路径。
* 每次遇到一个节点时,先记录'0',表示访问该节点,然后访问其所有子节点,最后记录'1',表示返回父节点。
*/
import java.util.*;
import java.util.stream.Collectors;
public class EvolutionTreeStream {
public String getEvolutionSequence(int[] parents) {
Map<Integer, List<Integer>> tree = new HashMap<>();
for (int i = 0; i < parents.length; i++) {
tree.computeIfAbsent(parents[i], k -> new ArrayList<>()).add(i);
}
StringBuilder sb = new StringBuilder();
dfs(0, tree, sb);
return sb.toString();
}
private void dfs(int node, Map<Integer, List<Integer>> tree, StringBuilder sb) {
sb.append('0'); // 记录当前节点
if (tree.containsKey(node)) {
tree.get(node).stream()
.sorted() // 确保以字典序遍历
.forEach(child -> dfs(child, tree, sb));
}
sb.append('1'); // 返回到父节点
}
public static void main(String[] args) {
EvolutionTreeStream et = new EvolutionTreeStream();
int[] parents1 = {-1, 0, 0, 2};
System.out.println(et.getEvolutionSequence(parents1)); // 输出: 00110
int[] parents2 = {-1, 0, 0, 1, 2, 2};
System.out.println(et.getEvolutionSequence(parents2)); // 输出: 00101100
}
}
解释
方法:
题解采用深度优先搜索(DFS)的方法来构建演化序列。首先,使用一个字典 `m1` 来存储每个节点及其对应的子节点列表。这是通过遍历 `parents` 数组得到的,其中每个元素的索引表示节点,值表示其父节点。对于根节点(其父节点为 `-1`),启动DFS过程。在DFS函数 `build_str` 中,对于每个节点,首先获取其所有子节点,并对每个子节点递归调用 `build_str`。每次递归返回的字符串表示该子节点及其所有后代的演化过程。对这些字符串进行排序,确保按字典序最小方式合并。每个子节点序列前后分别添加 '0' 和 '1',以模拟在该节点下添加新子节点和回退到父节点的操作。最后,返回构建的字符串,保留到最后一个 '0' 以确保不会多余地回退到根节点之外。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
在构建字符串时,为什么每个子节点的演化序列需要用'0'开始和'1'结束,这样的表示有什么特殊意义吗?
▷🦆
DFS函数中对子节点序列进行排序的原因是什么?排序是否对最终的字典序最小结果有决定性影响?
▷🦆
题解中提到的最后一个'0'的查找方法(ret.rfind('0')+1)是为了什么目的?能否具体解释其在字符串构建中的作用和必要性?
▷