📌  相关文章
📜  N叉树的每个节点的具有较小值的祖先的计数

📅  最后修改于: 2022-05-13 01:57:12.908000             🧑  作者: Mango

N叉树的每个节点的具有较小值的祖先的计数

给定一个由 N 个节点组成的N树,其值从1 到 N以 1 为根,对于所有节点,打印具有比当前节点更小的值的祖先的数量。

例子:

蛮力方法:这个想法类似于这里提到的:为二叉树的每个节点计算具有较小值的祖先。这个想法是对每个节点使用DFS ,并且可以很容易地扩展到N 叉树

时间复杂度: O(N 2 )
辅助空间: O(1)

高效方法:高效方法基于 Ordered_set、基于策略的数据结构和 DFS 的概念。

  • 使用自顶向下的 DFS从根遍历到所有节点,并使用有序集存储从根到当前节点的路径中所有节点的值。
  • 每当进入一个节点时,在对其子节点调用 DFS 之前,将节点索引推有序集中,每当我们退出节点时,从有序集中删除节点索引。这确保了 ordered_set 将包含当前节点的所有祖先的值。
  • 由于有序集提供了通过查找x的顺序来返回比给定x更小的值的功能,因此对于每个节点,每当进入节点时,只需找到当前节点索引的顺序并获取较小值的数量存在于ordered_set 中,即每个节点的较小值祖先的数量。
  • 使用地图存储每个节点的较小值祖先的数量,并使用它来打印最终答案。

下面是上述方法的实现。

C++
// C++ program for the above approach
#include 
  
// Common file
#include 
  
// Including tree_order_statistics_node_update
#include 
  
using namespace std;
using namespace __gnu_pbds;
  
// Declaring ordered_set
typedef tree,
             rb_tree_tag,
             tree_order_statistics_node_update>
    ordered_set;
  
// Map to store final ans for each node
unordered_map ans;
  
// Function to add an edge
// between nodes u and v
void addEdge(vector adj[],
             int u, int v)
{
    adj[u].push_back(v);
    adj[v].push_back(u);
}
  
// Function to count the number of
// ancestors with values smaller
// than that of the current node
void countSmallerAncestors(
    vector adj[],
    int root, int par,
    ordered_set& ancestors)
{
  
    // Map current node to
    // number of smaller valued ancestors
    ans[root] = ancestors.order_of_key(root);
  
    // Add current node to path
    ancestors.insert(root);
    for (int node : adj[root]) {
  
        // Avoid cycles
        if (node != par) {
            countSmallerAncestors(
                adj, node,
                root, ancestors);
        }
    }
  
    // Remove current node from path
    ancestors.erase(root);
}
  
// Driver Code
int main()
{
    // Number of nodes in graph
    int N = 7;
  
    // Initialize graph
    vector adj[N + 1];
  
    // Tree Formation
    addEdge(adj, 1, 5);
    addEdge(adj, 1, 4);
    addEdge(adj, 4, 6);
    addEdge(adj, 5, 3);
    addEdge(adj, 5, 2);
    addEdge(adj, 5, 7);
  
    // Ordered set to store values in path
    // from root to current node in dfs
    ordered_set ancestors;
  
    countSmallerAncestors(adj, 1, -1, ancestors);
  
    for (int i = 1; i <= N; i++) {
        cout << ans[i] << " ";
    }
  
    return 0;
}


输出:
0 1 1 1 1 2 2

时间复杂度: O(N * log(N))。
辅助空间: O(N)。