当前位置: 首页 > news >正文

千问 LeetCode 2791. 树中可以形成回文的路径数 Java实现

这是一道经典的树上路径计数问题,结合了状态压缩和异或(XOR)的技巧。

核心思路

1. 回文判断条件:一个字符串的字符重新排列后能形成回文,当且仅当字符串中最多只有一个字符出现了奇数次,其余字符均出现偶数次。
2. 状态压缩与异或:由于字符串只包含小写字母(26个),我们可以用一个 26 位的二进制数(int 类型)来表示当前路径上各字符出现次数的奇偶性。某一位为 1 表示该字符出现了奇数次,为 0 表示出现了偶数次。在树上遍历时,向下走一条边相当于对该边字符对应的二进制位进行异或操作。
3. 路径转化:树上任意两点 u 到 v 的路径,可以看作是从 u 到根节点,再从根节点到 v 的路径。其中,从 u 和 v 的最近公共祖先(LCA)到根节点的这段路径被重复走了两次(一去一回),字符出现次数必然为偶数(异或后为0),不影响回文判断。因此,我们只需要记录每个节点到根节点的路径状态。
4. 计数逻辑:使用 DFS 遍历树,并用一个哈希表(HashMap)记录遍历过程中,各种路径状态出现的次数。对于当前节点,如果之前存在一个节点到根节点的状态与当前状态完全相同(异或结果为0,所有字符均为偶数次)或仅相差一位(异或结果只有一个1,仅一个字符为奇数次),那么这两个节点之间的路径就能形成回文。

Java 代码实现

import java.util.*;

class Solution {
public long countPalindromePaths(List<Integer> parent, String s) {
int n = parent.size();
// 1. 构建邻接表(树结构)
List<Integer>[] children = new ArrayList[n];
Arrays.setAll(children, e -> new ArrayList<>());
for (int i = 1; i < n; i++) {
int p = parent.get(i);
children[p].add(i);
}

// 2. 哈希表记录从根节点到当前路径的状态(异或值)出现的次数
// 初始放入 0:1,代表根节点之上的空路径状态
Map<Integer, Integer> count = new HashMap<>();
count.put(0, 1);

return dfs(0, 0, children, s.toCharArray(), count);
}

private long dfs(int node, int status, List<Integer>[] children, char[] chars, Map<Integer, Integer> count) {
long res = 0;

for (int child : children[node]) {
// 计算从根节点到子节点 child 的路径状态
// 异或上当前边上的字符对应的位
int childStatus = status ^ (1 << (chars[child] - 'a'));

// 情况1:之前有相同状态的路径(所有字符出现偶数次,异或后为0)
res += count.getOrDefault(childStatus, 0);

// 情况2:之前有仅相差一个字符奇偶性的路径(仅一个字符出现奇数次)
for (int i = 0; i < 26; i++) {
res += count.getOrDefault(childStatus ^ (1 << i), 0);
}

// 将当前子节点的状态加入哈希表,供后续节点匹配
count.put(childStatus, count.getOrDefault(childStatus, 0) + 1);

// 继续向下 DFS
res += dfs(child, childStatus, children, chars, count);
}
return res;
}
}

复杂度分析
* 时间复杂度:O(n * A),其中 n 是节点数量,A 是字符集大小(本题为26)。每个节点只会被遍历一次,每次遍历需要枚举 26 个字母来寻找只差一位的状态。
* 空间复杂度:O(n),主要用于存储树的邻接表以及哈希表。在最坏情况下(如链状树),哈希表可能存储 O(n) 个不同的状态。

http://www.rkmt.cn/news/1417837.html

相关文章:

  • 2026年5月市面上GEO公司哪家好厂家推荐榜,AI直播托管/数字人运营/GEO全域流量搭建厂家选择指南 - 海棠依旧大
  • 联想拯救者Y7000系列BIOS隐藏选项一键解锁终极指南
  • 告别WebGL!用Unity Embedded Browser插件打造高性能PC端混合应用界面
  • 千问 LeetCode 2801. 统计范围内的步进数字数目 Java实现
  • 【Elasticsearch从入门到精通】第57篇:Elasticsearch查询性能优化——慢查询分析与优化策略
  • 如何快速实现代码高亮:hilite.me的终极指南
  • 从 Copilot 到 Autopilot 升级路线图 需要补齐的五个能力
  • OpenCV项目实战:给你的C++图像处理程序加上自定义字体和中文水印
  • 5分钟快速上手:使用Unlock-Music在浏览器中解锁加密音乐文件完整指南
  • 2026 年 5 月证券从业备考避坑:培训 APP 与刷题资料实测指南 - 讲清楚了
  • LeetCode LeetCode 2801. 统计范围内的步进数字数目 C++实现
  • CloudCanal 免费社区版:全自研数据迁移同步工具,功能对标大厂,亮点特性与优化修复齐上阵!
  • 5 款中老年时光相册工具实测,轻松留存人生回忆
  • 浏览器内秒级构建容器镜像,开发者工作流或迎变革
  • 2026现阶段杭州万能话筒优质厂家推荐几家:市场主流品牌选购攻略 - 2026年企业资讯
  • 2026中山工厂搬家公司推荐:实测5家靠谱不踩雷 - 从来都是英雄出少年
  • Qwen模型 LeetCode 2809. 使数组和小于等于 x 的最少时间 Java实现
  • Inno Setup 6.7.3 版本发布:改进 Wine RichEdit 方法、修复安全问题及函数编译问题
  • 基于PIR传感器与分立元件的智能花园驱鸟器DIY全解析
  • 2026 中山搬工厂公司实测盘点与避坑指南 - 从来都是英雄出少年
  • Cursor 3.3 终极技能解释:12个斜杠命令解锁AI编程
  • 太阴间了!程序员要加班到晚 10 点,但有人想方设法不让程序员“偷用公司空调”
  • Keil μVision4项目实战:手把手教你用T5L迪文屏给51单片机加个“漂亮脸蛋”
  • 【紧急更新】2024Q3最新版:ChatGPT汇报材料优化SOP(含中办公文格式API适配参数+敏感词动态过滤表)
  • 通达信缠论插件终极指南:3步实现自动化笔段中枢识别
  • 供水管网及泵站远程监控运维管理系统方案
  • 全球首例实战!伊朗APT Nimbus Manticore用AI打造MiniFast后门,深度解析AI驱动的网络战新形态
  • 3分钟诊断Windows热键冲突:Hotkey Detective帮你找回失效的快捷键
  • 2026年四川集装箱厂家TOP5排行:成都集装箱厂家、景区移动厕所、海运箱改造、环保公厕生产厂家、移动厕所出租选择指南 - 优质品牌商家
  • Windows 11/10 资源管理器卡死别慌!这3种重启explorer.exe的方法总有一个能救急