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

DeepSeek LeetCode 3786. 树组的交互代价总和 Java实现

问题描述

给定一棵 n 个节点的无向树(节点编号 0 到 n-1),以及一个长度相同的数组 group,group[i] 表示节点 i 的分组标签。两个节点 u 和 v 若 group[u] == group[v],则它们属于同一组。交互代价定义为树上两节点之间唯一路径的边数。要求返回所有同组无序节点对的交互代价总和。

核心思路:边贡献统计法

直接枚举所有同组节点对并计算路径长度,时间复杂度为 O(n²),对于 n ≤ 10⁵ 会超时。

核心转化:总代价 = 每条边被同组节点对经过的次数之和。

对于任意一条边,若将其从树中移除,树会被分成两部分。假设某组在这条边的一侧子树中有 x 个节点,该组总共有 k 个节点,则该组中路径经过这条边的节点对数量为 x * (k - x)。

因此只需一次 DFS,统计每个子树中各分组的节点数量,累加每条边的贡献即可。

Java 实现

```java
import java.util.ArrayList;
import java.util.List;

class Solution {
private long totalCost = 0;
private int[][] counts; // counts[u][g] = 以u为根的子树中分组g的节点数
private int[] totalInGroup; // 全树中各分组的总节点数
private List<List<Integer>> adj;

public long interactionCosts(int n, int[][] edges, int[] group) {
// 1. 构建邻接表
adj = new ArrayList<>();
for (int i = 0; i < n; i++) {
adj.add(new ArrayList<>());
}
for (int[] edge : edges) {
adj.get(edge[0]).add(edge[1]);
adj.get(edge[1]).add(edge[0]);
}

// 2. 统计各分组总节点数(分组标签范围为 1 到 20)
totalInGroup = new int[21];
for (int g : group) {
totalInGroup[g]++;
}

// 3. DFS 统计子树中各分组节点数,并累加边的贡献
counts = new int[n][21];
dfs(0, -1, group);

return totalCost;
}

private void dfs(int u, int p, int[] group) {
// 当前节点自身属于其分组
counts[u][group[u]] = 1;

for (int v : adj.get(u)) {
if (v == p) continue;

dfs(v, u, group);

// 对每个分组,计算边 (u, v) 的贡献
for (int g = 1; g <= 20; g++) {
if (totalInGroup[g] < 2) continue; // 该组不足2个节点,无有效节点对

long inSubtree = counts[v][g]; // 子树v中分组g的节点数
long outsideSubtree = totalInGroup[g] - inSubtree; // 子树外同组节点数

// 该组中路径经过这条边的节点对数量 = inSubtree * outsideSubtree
totalCost += inSubtree * outsideSubtree;
}

// 将子树v的统计结果合并到u
for (int g = 1; g <= 20; g++) {
counts[u][g] += counts[v][g];
}
}
}
}
```

代码说明

1. 数据结构:counts[u][g] 存储以 u 为根的子树中分组 g 的节点数量;totalInGroup[g] 存储全树中分组 g 的节点总数。
2. DFS 遍历:从根节点 0 开始递归遍历。对于每个子节点 v,先递归处理 v 的子树,得到 counts[v][g]。
3. 边贡献计算:对于边 (u, v),counts[v][g] 是边下方子树中分组 g 的节点数,totalInGroup[g] - counts[v][g] 是边上方同组节点数。二者的乘积就是该组中路径经过这条边的节点对数量。
4. 结果合并:将子树的统计结果累加到父节点 counts[u][g] 中。

复杂度分析

· 时间复杂度:O(n × G),其中 G 是不同分组的数量(本题中 G ≤ 20),实际为 O(20n)
· 空间复杂度:O(n × G) 用于存储 counts 数组

http://www.jsqmd.com/news/1298921/

相关文章:

  • Pandas数据处理入门:从数据清洗到分析导出的完整实战指南
  • TCP协议核心机制与网络故障排查实战指南
  • ORBOTECH 0437974B-T 采集卡
  • 母婴家政上门派单多端管理平台开发技术解析
  • 镇江市防水补漏_2026苏南长江运河交汇城市漏水维修价格行情与五大正规团队推荐 - 雨婺虹房屋维修
  • 2026年4款OPPO录音总结哪个好?实测对比后帮你选出合适的款
  • SpringBoot水果电商系统开发与架构设计实践
  • GoF设计模式——工厂方法模式
  • SVPWM算法原理与Simulink仿真实现:从电压矢量调制到电机控制
  • 深入解析U-Boot:嵌入式系统启动流程与BootLoader核心技术
  • 【AI 风向标】Reddit是什么?一文读懂全球最大兴趣社区平台
  • 近期Deepseek问题汇总2026年7月
  • 3分钟掌握手机号码定位查询:免费开源工具让你秒查归属地
  • 网络OSI七层模型是什么
  • LVGL标签控件深度解析:从基础显示到嵌入式GUI性能优化
  • C++十大排序算法全解析:从原理到实战应用指南
  • Godot多人游戏暂停菜单实现与性能优化实战
  • 2026甄选:专业装修公司与个性化设计品牌机构深度解析 - 优企名品
  • 仅限本周开放下载:《AI搜索产品对比决策手册》PDF(含可编辑选型评分表+供应商SLA条款审查清单+POC验收Checklist),错过再等半年更新
  • C/C++ Debug与Release混用:内存炸弹的成因与系统解决方案
  • 2026年 非标压铸模胚供应厂家:高精度定制与耐用品质优选 - 优企名品
  • Linux C语言Socket编程入门:从TCP通信到Echo服务器实战
  • 河南数据分析培训机构怎么选?2026年郑州靠谱机构盘点
  • C#与.NET框架核心架构解析:从CLR到现代语言特性
  • SAP-ABAP: ADOBE表单样式定制:JavaScript脚本、动态样式、二维码/条形码嵌入开发
  • STM32红外接收电路设计:电平转换与RC滤波实战指南
  • Python虚拟环境全解析:从venv到poetry,告别依赖地狱
  • ncRNA酵母双杂交技术:优化RNA-蛋白质互作检测方案
  • Mermaid Live Editor终极指南:5分钟学会免费在线图表编辑神器!
  • 自动化保研面试:从控制理论到工程实践的全方位准备指南