LeeCode 834 DFS

题意

传送门 LeeCode 834. 树中距离之和

题解

枚举根节点 D F S DFS DFS 复杂度 O ( n 2 ) O(n^2) O(n2),实际上一次 D F S DFS DFS 已经获取了以各节点为根的子树的信息,利用这些信息进行优化。

s u m [ i ] , n u m [ i ] sum[i], num[i] sum[i],num[i] 分别为节点 i i i 为根的子树的树中距离和与树中节点个数, c h ch ch 为节点 i i i 的子节点,则有
{ s u m [ i ] = ∑ ( s u m [ c h ] + n u m [ c h ] ) n u m [ i ] = ∑ n u m [ c h ] \begin{cases}sum[i]=\sum(sum[ch]+num[ch])\\ num[i]=\sum num[ch] \\ \end{cases} {sum[i]=(sum[ch]+num[ch])num[i]=num[ch] 观察根节点的子节点 c h ch ch,只需要其父节点与子节点的信息,就可以求出 s u m [ c h ] sum[ch] sum[ch]。这是因为根节点记录了整棵树的节点信息,那么只需要减去子节点 c h ch ch 的部分,就可以获得整棵树中除了以 c h ch ch 为根节点的子树以外的部分的信息。那么更新节点 c h ch ch 后,节点 c h ch ch 记录了以 c h ch ch 为根节点的整棵树的信息。那么按照递归深度 O ( 1 ) O(1) O(1) 不断更新节点为新的根节点即可。设 p p p 为当前节点的父节点,则有
{ s u m [ c h ] = ∑ { s u m [ c h ] + ( s u m [ p ] − s u m [ c h ] − n u m [ c h ] ) + n u m [ p ] − n u m [ c h ] } n u m [ c h ] = n u m [ p ] \begin{cases}sum[ch]=\sum\{sum[ch]+(sum[p]-sum[ch]-num[ch])+num[p]-num[ch]\}\\ num[ch]=num[p] \\ \end{cases} {sum[ch]={sum[ch]+(sum[p]sum[ch]num[ch])+num[p]num[ch]}num[ch]=num[p]

那么一次 D F S DFS DFS 预处理出以各节点为根节点的子树路径和与节点数;再一次 D F S DFS DFS 更新根节点,求解答案即可。

class Solution
{
public:
    void pre_dfs(int v, int p, vector<vector<int>> &G, vector<int> &sum, vector<int> &num)
    {
        int s = 0, n = 1;
        for (int i = 0; i < G[v].size(); i++)
        {
            int u = G[v][i];
            if (u != p)
            {
                pre_dfs(u, v, G, sum, num);
                s += sum[u] + num[u], n += num[u];
            }
        }
        sum[v] = s, num[v] = n;
    }
    void dfs(int v, int p, vector<vector<int>> &G, vector<int> &sum, vector<int> &num)
    {
        if (p != -1)
        {
            sum[v] = sum[p] + num[p] - (num[v] << 1);
            num[v] = num[p];
        }
        for (int i = 0; i < G[v].size(); i++)
        {
            int u = G[v][i];
            if (u != p)
            {
                dfs(u, v, G, sum, num);
            }
        }
    }
    vector<int> sumOfDistancesInTree(int N, vector<vector<int>> &edges)
    {
        vector<vector<int>> G(N);
        for (auto e : edges)
        {
            G[e[0]].push_back(e[1]);
            G[e[1]].push_back(e[0]);
        }
        vector<int> sum(N), num(N);
        int root = 0;
        pre_dfs(root, -1, G, sum, num);
        dfs(root, -1, G, sum, num);
        return sum;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值