📌  相关文章
📜  Q查询在给定子树中具有奇数除数的节点数(1)

📅  最后修改于: 2023-12-03 15:19:39.644000             🧑  作者: Mango

查询在给定子树中具有奇数除数的节点数

介绍

本题要求在给定的一棵树中,查询子树中具有奇数除数的节点数。这是一道树型动态规划问题,需要用到以下知识点:

  • 深度优先搜索(DFS)
  • 前缀和(Prefix Sum)
思路

我们可以使用深度优先搜索(DFS)遍历整棵树。在遍历每个节点时,我们记录从根节点到该节点的路径上每个节点的值的前缀和。这样,我们就可以快速计算出任何子树的值的前缀和。

然后我们需要计算每个节点的子树中具有奇数除数的节点数量。对于每个节点,我们可以将其子树的前缀和按奇偶性分类,使用前缀和的概念统计每个分类中的节点数量。

最后,我们可以在DFS的过程中,使用一个变量来保存答案,最终返回该变量即可。

代码
class Solution:
    def numOfSubtreesWithOddSum(self, n: int, edges: List[List[int]]) -> List[int]:
        mod = int(1e9) + 7
        
        # 构建邻接表
        graph = [[] for _ in range(n)]
        for u, v in edges:
            graph[u - 1].append(v - 1)
            graph[v - 1].append(u - 1)
        
        # DFS计算前缀和
        prefix_sum = [0] * n
        def dfs(node, parent):
            nonlocal prefix_sum
            prefix_sum[node] = (prefix_sum[parent] + node) % 2
            odd_cnt = 1 if prefix_sum[node] == 1 else 0
            even_cnt = 1 if prefix_sum[node] == 0 else 0
            for child in graph[node]:
                if child != parent:
                    dfs(child, node)
                    odd_cnt += cnt_odd[child]
                    even_cnt += cnt_even[child]
            cnt_odd[node] = odd_cnt
            cnt_even[node] = even_cnt
        
        # 计算子树中具有奇数除数的节点数量
        cnt_odd = [0] * n
        cnt_even = [0] * n
        dfs(0, 0)
        ans = [cnt_odd[i] * (n - cnt_odd[i]) + cnt_even[i] * (n - cnt_even[i]) for i in range(n)]
        return [x % mod for x in ans]
复杂度分析
  • 时间复杂度:$O(n)$,其中 $n$ 为节点数,需要遍历每个节点一次。
  • 空间复杂度:$O(n)$,需要存储前缀和、每个节点子树中具有奇数除数的节点数量、邻接表等信息。