树中的路径和 Sum of Distances in Tree

2019-03-28 15:25:43

问题描述:

问题求解:

写过的最好的Hard题之一。

初看本题,很经典的路径和嘛,dfs一遍肯定可以得到某个节点到其他所有节点的距离和。这种算法的时间复杂度是O(n ^ 2)。看一下数据量,emmm,果然不行。这个数据量一看就知道只能是O(n)的算法了。

只遍历一遍最多只能得到一个解,因此本题肯定是需要遍历至少两遍的。

在第一遍遍历的时候我们需要保存下两个值,一个是当前节点的subtree的路径总和,一个是当前节点的subtree的总的节点数。

在第二遍遍历的时候,我们已经知道root节点的值已经是最终的结果了,这个时候当我们将根节点从root移动到其child的时候,有cnt[child]的节点数的离现在的根节点近了一步,有N - cnt[child]的节点到当前根节点远了一步,所以res[child] = res[root] - cnt[child] + N - cnt[child]。这样再次遍历所有节点更新res数组得到的结果就是我们需要的最终的答案。

    public int[] sumOfDistancesInTree(int N, int[][] edges) {
        List<Set<Integer>> graph = new ArrayList<>();
        int[] res = new int[N];
        int[] cnt = new int[N];
        for (int i = 0; i < N; i++) graph.add(new HashSet<>());
        for (int[] edge : edges) {
            graph.get(edge[0]).add(edge[1]);
            graph.get(edge[1]).add(edge[0]);
        }
        dfs1(0, -1, res, cnt, graph);
        dfs2(0, -1, res, cnt, graph);
        return res;
    }

    private void dfs1(int root, int parent, int[] res, int[] cnt, List<Set<Integer>> graph) {
        for (int node : graph.get(root)) {
            if (node == parent) continue;
            dfs1(node, root, res, cnt, graph);
            cnt[root] += cnt[node];
            res[root] += res[node] + cnt[node];
        }
        cnt[root] += 1;
    }

    private void dfs2(int root, int parent, int[] res, int[] cnt, List<Set<Integer>> graph) {
        for (int node : graph.get(root)) {
            if (node == parent) continue;
            res[node] = res[root] - cnt[node]  + cnt.length - cnt[node];
            dfs2(node, root, res, cnt, graph);
        }
    }

  

扫描二维码关注公众号,回复: 5694566 查看本文章

猜你喜欢

转载自www.cnblogs.com/TIMHY/p/10615394.html