LeetCode 2246. 相邻字符不同的最长路径 递归 + 深度优先搜索 (DFS)详解

2246. 相邻字符不同的最长路径

题目来源

2246. 相邻字符不同的最长路径

题目分析

给定一个字符串 s 和一个长度为 nparent 数组,其中 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 all 1 <= i <= n - 1
  • parent[0] == -1
  • parent represents a valid tree.

解题思路

思路:递归 + 深度优先搜索 (DFS)

  1. 定义问题

    • 目标是在树中寻找最长路径,路径上的任意两个相邻节点所对应的字符必须不同。
  2. 状态转移

    • 利用 DFS 递归遍历整棵树,计算以每个节点为根的最长路径,并更新全局最大路径。
  3. 递归公式

    • 对于每个节点 i,我们通过 DFS 递归计算其子树中满足条件的最长路径。如果该路径经过当前节点且与父节点字符不同,则更新全局最大路径。
  4. 最终结果

    • 通过 DFS 遍历整棵树,并在每次递归时更新最大路径长度 ans,最终 ans 即为所求的最长路径长度。

核心算法步骤

  1. 构建树结构

    • 根据 parent 数组构建出树的结构,其中 parentList 用于存储每个节点的子节点列表。
  2. DFS 递归

    • 从根节点开始,通过 DFS 遍历整棵树,在遍历过程中计算每个节点与其子节点之间满足条件的最长路径,并更新全局最大路径 ans
  3. 返回最长路径

    • 每次递归返回当前节点为根节点的最长路径长度。

代码实现

以下是求解相邻字符不同的最长路径的 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 算法,我们可以有效地求解相邻字符不同的最长路径问题。此方法思路清晰,易于实现,且具有较高的效率。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值