N叉树的每个节点的具有较小值的祖先的计数
给定一个由 N 个节点组成的N叉树,其值从1 到 N以 1 为根,对于所有节点,打印具有比当前节点更小的值的祖先的数量。
例子:
Input: Below is the given Tree:
1
/ \
4 5
/ / | \
6 3 2 7
Output: 0 1 1 1 1 2 2
Explanation:
Since node 1 is the root node, it has no ancestors.
Ancestors of node 2: {1, 5}. Number of ancestors having value smaller than 2 is 1.
Ancestors of node 3: {1, 5}. Number of ancestors having value smaller than 3 is 1.
Ancestors of node 4: {1}. Number of ancestors having value smaller than 4 is 1.
Ancestors of node 5: {1}. Number of ancestors having value smaller than 5 is 1.
Ancestors of node 6: {1, 4}. Number of ancestors having value smaller than 6 is 2.
Ancestors of node 7: {1, 5}. Number of ancestors having value smaller than 7 is 2
Input: Below is the given Tree:
1
/ \
3 2
\
4
Output: 0 1 1 2
Explanation:
Node 1 has no ancestors.
Ancestors of node 2: {1}. Number of ancestors having value smaller than 2 is 1.
Ancestors of node 3: {1}. Number of ancestors having value smaller than 3 is 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)。