1. 程式人生 > 實用技巧 >834. 樹中距離之和-dfs/dp/樹-困難

834. 樹中距離之和-dfs/dp/樹-困難

問題描述

給定一個無向、連通的樹。樹中有 N 個標記為 0...N-1 的節點以及 N-1條邊。

第 i 條邊連線節點edges[i][0] 和 edges[i][1]。

返回一個表示節點 i 與其他所有節點距離之和的列表 ans。

示例 1:

輸入: N = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]]
輸出: [8,12,6,10,10,10]
解釋:
如下為給定的樹的示意圖:
0
/ \
1 2
/|\
3 4 5

我們可以計算出 dist(0,1) + dist(0,2) + dist(0,3) + dist(0,4) + dist(0,5)
也就是 1 + 1 + 2 + 2 + 2 = 8。 因此,answer[0] = 8,以此類推。
說明:1 <= N <= 10000

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/sum-of-distances-in-tree

解答

//每個節點到全域性的距離,可以由父親節點到全域性的距離推出來
class Solution {
    int[][] fa;
    Map<Integer, List<Integer>> map;
    boolean[] vi;
    int[] result;
    int num;
    public void dfs(int start){
        vi[start] = true;
        List
<Integer> temp = map.get(start); if(temp.size() == 1 && vi[temp.get(0)])return; for(int i:temp){ if(vi[i])continue; dfs(i); fa[start][0] += fa[i][0]+1; fa[start][1] += fa[i][0]+1 + fa[i][1]; } } public void dfs2(int
start){ vi[start] = true; List<Integer> temp = map.get(start); if(temp.size() == 1 && vi[temp.get(0)])return; for(int i:temp){ if(vi[i])continue; //本節點到全域性的距離可以由父親節點到全域性的距離推出來 //全域性距離 = 父親節點到其他節點的距離+外部節點個數+本身作為父節點到全部子節點的距離 result[i] = (result[start]-(fa[i][0]+fa[i][1]+1))+(num-fa[i][0]-1)+fa[i][1]; dfs2(i); } } public int[] sumOfDistancesInTree(int N, int[][] edges) { result = new int[N]; vi = new boolean[N]; if(N<=1)return result; map = new HashMap<>(); num = N; for(int[] edge:edges){ if(!map.containsKey(edge[0]))map.put(edge[0], new ArrayList<Integer>()); if(!map.containsKey(edge[1]))map.put(edge[1], new ArrayList<Integer>()); map.get(edge[0]).add(edge[1]); map.get(edge[1]).add(edge[0]); } fa = new int[N][2]; //0作為起點開始dfs dfs(0); result[0] = fa[0][1]; vi = new boolean[N]; dfs2(0); return result; } }