Algorithm 节点s的子树中值为x的节点数?

Algorithm 节点s的子树中值为x的节点数?,algorithm,data-structures,graph,tree,hashmap,Algorithm,Data Structures,Graph,Tree,Hashmap,我们得到一个根树,其中每个节点都有一些值。 我们的任务是处理要求计算节点s子树中值为x的节点数的查询。 我们也可以使用离线算法,因为没有更新查询。 因此,我们可以一次读取所有查询,然后按任意顺序处理它们 简单方法:对于每个查询计数(节点s,val x),从节点s开始一个DFS,计算其中值x的节点数 伪代码: DFS(节点s,int v): 如果(!s)返回0; cnt=0; 如果(s.val==v) cnt+=1; 对于(int i=0;i

我们得到一个根树,其中每个节点都有一些值。

我们的任务是处理要求计算节点s子树中值为x的节点数的查询。

我们也可以使用离线算法,因为没有更新查询。 因此,我们可以一次读取所有查询,然后按任意顺序处理它们

简单方法:对于每个查询计数(节点s,val x),从节点s开始一个DFS,计算其中值x的节点数

伪代码

DFS(节点s,int v):
如果(!s)返回0;
cnt=0;
如果(s.val==v)
cnt+=1;
对于(int i=0;i
复杂性

对于Q查询数,时间复杂度O(Q*N),其中N是树中的节点数

如何有效地回答查询?


这实际上可以在
O(n log n+q)
中使用一种称为
从小到大
(有时也称为
DSU on tree
sack
)的技术来完成

  • 首先,我们可以读取所有查询,并将需要处理的所有查询及其索引存储在每个节点的哈希表中(以便按顺序输出)

  • 然后,我们从根开始简单地在树上创建DFS:

    • 首先递归处理所有子级
    • 如果是leaft节点,则使用该叶包含的值创建一个新哈希表
    • 否则,我们将引用节点所有子节点的最大的哈希表,并将所有其他子哈希表值添加到该哈希表中
    • 现在我们有了节点子树中所有值的哈希表,所以我们可以使用简单的查找在O(1)时间内回答该节点中的所有查询
所以现在有一些证据证明为什么这实际上是
O(n log n)

  • DFS是
    O(n)
  • 对于我们创建的每个哈希表,只有当我们发现某个哈希表大于我们的哈希表时,我们才会复制它,所以在最坏的情况下,它将位于大小如下的哈希表上:
    1,2,4,8,16…
    换句话说,我们将在最坏的情况下将每个哈希表复制到另一个哈希表中
    O(logn)
    次,有
    O(n)
    哈希表总计,因此在最坏的情况下,这将花费
    O(n log n)
    时间

当然,所有这些都假设你有一个好的散列函数,如果你得到了太多的冲突,你可以简单地使用平衡二叉搜索树而不是散列表来获得仍然很好的复杂度
O(n log^2 n)

O(n^2)的空间复杂度有效吗?从child返回一个值映射?@vivek_23是的,该方法需要O(n^2)空间。@YashShah你能详细说明一下吗?@YashShah,但要构建O(n^2)空间,时间复杂度也会是O(n^2),对吗?所以基本上我们是在合并该节点的子哈希表后,计算每个节点在DFS调用()上的查询结果,对吗?@tusharawat是的
DFS(node s, int v): 

    if(!s) return 0;

    cnt = 0;
    if(s.val == v) 
        cnt += 1;

    for(int i = 0; i < s.children.size; i++) {
        cnt += DFS(s.children[i], v);
    }

    return cnt;