2246. 相邻字符不同的最长路径
2246. 相邻字符不同的最长路径
题目来源
题目分析
给定一个字符串
s
和一个长度为n
的parent
数组,其中parent[i]
是节点i
的父节点,节点0
是根节点。需要找到从根节点到任意节点之间,相邻字符不同的最长路径的长度。
题目难度
- 难度:困难
题目标签
- 标签:动态规划, 树
题目限制
2 <= s.length <= 10^5
0 <= parent.length <= s.length - 1
parent.length == n - 1
0 <= parent[i] <= n - 1
for all1 <= i <= n - 1
parent[0] == -1
parent
represents a valid tree.
解题思路
思路:递归 + 深度优先搜索 (DFS)
-
定义问题:
- 目标是在树中寻找最长路径,路径上的任意两个相邻节点所对应的字符必须不同。
-
状态转移:
- 利用 DFS 递归遍历整棵树,计算以每个节点为根的最长路径,并更新全局最大路径。
-
递归公式:
- 对于每个节点
i
,我们通过 DFS 递归计算其子树中满足条件的最长路径。如果该路径经过当前节点且与父节点字符不同,则更新全局最大路径。
- 对于每个节点
-
最终结果:
- 通过 DFS 遍历整棵树,并在每次递归时更新最大路径长度
ans
,最终ans
即为所求的最长路径长度。
- 通过 DFS 遍历整棵树,并在每次递归时更新最大路径长度
核心算法步骤
-
构建树结构:
- 根据
parent
数组构建出树的结构,其中parentList
用于存储每个节点的子节点列表。
- 根据
-
DFS 递归:
- 从根节点开始,通过 DFS 遍历整棵树,在遍历过程中计算每个节点与其子节点之间满足条件的最长路径,并更新全局最大路径
ans
。
- 从根节点开始,通过 DFS 遍历整棵树,在遍历过程中计算每个节点与其子节点之间满足条件的最长路径,并更新全局最大路径
-
返回最长路径:
- 每次递归返回当前节点为根节点的最长路径长度。
代码实现
以下是求解相邻字符不同的最长路径的 Java 代码:
/**
* 2246. 相邻字符不同的最长路径
* @param parent 父节点数组
* @param s 字符串
* @return 最长路径长度
*/
public int longestPath(int[] parent, String s) {
int n = parent.length;
this.chars = s.toCharArray();
for (int i = 0; i < n; i++) {
parentList.add(new ArrayList<>());
}
for (int i = 1; i < n; i++) {
parentList.get(parent[i]).add(i);
}
longestPath2(0, -1);
return ans + 1;
}
private int ans = 0;
private final List<List<Integer>> parentList = new ArrayList<>();
private char[] chars;
public int longestPath2(int i, int j) {
int maxlen = 0;
for (int k : parentList.get(i)) {
int klen = longestPath2(k, i) + 1;
if (this.chars[k] != this.chars[i]) {
ans = Math.max(ans, maxlen + klen);
maxlen = Math.max(maxlen, klen);
}
}
return maxlen;
}
代码解读
longestPath2(int i, int j)
是一个递归函数,用于计算以当前节点i
为根的子树中相邻字符不同的最长路径。maxlen
用于记录当前节点与其子节点之间的最长路径。ans
用于存储全局的最长路径,并在每次递归过程中更新。
性能分析
- 时间复杂度:
O(N)
,其中N
是树的节点数量。每个节点遍历一次。 - 空间复杂度:
O(N)
,由于递归栈的空间开销和树结构的存储。
测试用例
以下是一些测试用例,用于验证代码的正确性:
int[] parent1 = {-1, 0, 0, 1, 1, 2};
String s1 = "abacbe";
System.out.println(longestPath(parent1, s1)); // 输出: 4
int[] parent2 = {-1, 0, 0, 0};
String s2 = "aabc";
System.out.println(longestPath(parent2, s2)); // 输出: 3
int[] parent3 = {-1, 0, 1, 2, 3};
String s3 = "abbbb";
System.out.println(longestPath(parent3, s3)); // 输出: 2
总结
通过递归和 DFS 算法,我们可以有效地求解相邻字符不同的最长路径问题。此方法思路清晰,易于实现,且具有较高的效率。