class Solution {
private List<Integer>[] g;
private int[] ans,size;
public int[] sumOfDistancesInTree(int n, int[][] edges) {
ans = new int[n];
size = new int[n];
g = new ArrayList[n];
//Arrays.setAll(g,e -> new ArrayList<>());
for(int i = 0;i < n;i++){ //首先定义的是一个List一维数组 然后再分别在每一个数组中g[i] 再建立List数组
g[i] = new ArrayList<>();
}
for(var e : edges){ //将相连的边加上
int x = e[0], y = e[1]; //此处居然不可以省 只能写个临时变量填进去!!!!好奇怪的
g[x].add(y);
g[y].add(x);
}
dfs(0,-1,0);//0没有父节点
reroot(0,-1);
return ans;
}
//dp总得初始化吧 这样别的点才可以由此推导出来 此处函数就是初始化ans[0]->从0开始dfs,累加0到每个点的距离
//同时计算每棵子树size[i] 以便换根计算
private void dfs(int root,int fa,int depth){ //此处的root为递归到某个节点将其看做临时的根节点 但是fa又是递归到她的父节点
//由于采用递归所以depth即为深度 ans刚好就加上每个节点的depth就表示与0的距离了 递归到每个节点 就可以都加上
ans[0] += depth;//累加0到每个节点的距离 即完成ans[0]的初始化
size[root] = 1;//每个节点所包含的子树 包括自己;初始化就为1
for(int neigh : g[root]){
if(neigh != fa){ //此处避免递归到父节点
dfs(neigh,root,depth+1);
size[root] += size[neigh];//注意递归我是直接谈到底部 返回的时候才会进行计算返回值
}
}
}
private void reroot(int root,int fa){
for(int neigh : g[root]){
if(neigh != fa){
ans[neigh] += ans[root] + g.length - 2 * size[neigh];
reroot(neigh,root);
}
}
}
}
/*
基本思路:主函数中 dfs暴搜每个点并标记已搜过的点,在暴搜每个点时调用dfs函数()
dfs()函数基本思路也是暴搜加上数组值()也就是距离 然后返回长度和。 没看懂题胡诌!!!
ans[i] 节点i与其他所有节点距离之和
size[i]表示节点i下属的子树包含的子节点的个数 也包含自身
*/
动态规划--树形DP之换根DP(834. 树中距离之和)
于 2023-07-16 23:48:26 首次发布