Given an N-ary tree consisting of N nodes with values from 1 to N rooted at 1, for all nodes, print the number of ancestors having a smaller value than the current node.
Example:
Input: Below is the given Tree:
1
/ \
4 5
/ / | \
6 3 2 7Output: 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 2Input: Below is the given Tree:
1
/ \
3 2
\
4Output: 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.
Brute Force Approach: The idea is similar to what is mentioned here: Count ancestors with smaller value for each node of a Binary Tree. The idea is to use DFS for each node and can be extended to an N-ary tree easily.
Time Complexity: O(N2)
Auxiliary Space: O(1)
Efficient Approach: The efficient approach is based on the concept of Ordered_set, policy-based data structure, and DFS.
- Use a top-down DFS to traverse from the root to all the nodes and use an ordered set to store values of all nodes in the path from the root to the current node.
- Whenever entering a node, before calling DFS on its children, push the node index into the ordered set and whenever we exit the node, erase the node index from the ordered_set. This ensures that ordered_set will contain values of all ancestors of the current node.
- Since the ordered set gives the functionality to return a number of smaller values than given x by finding the order of the x, for each node, whenever entering the node, simply find the order of the current node’s index and get the number of smaller values present in the ordered_set i.e number of smaller valued ancestors for each node.
- Use a map to store the number of smaller valued ancestors for each node and use that to print the final answer.
Below is the implementation of the above approach.
// C++ program for the above approach #include <bits/stdc++.h> // Common file #include <ext/pb_ds/assoc_container.hpp> // Including tree_order_statistics_node_update #include <ext/pb_ds/tree_policy.hpp> using namespace std;
using namespace __gnu_pbds;
// Declaring ordered_set typedef tree< int , null_type, less< int >,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;
// Map to store final ans for each node unordered_map< int , int > ans;
// Function to add an edge // between nodes u and v void addEdge(vector< int > 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< int > 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< int > 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;
} |
//Java program for the above approach import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
class ordered_set implements Comparable<Integer> {
Set<Integer> tree;
public ordered_set() {
tree = new TreeSet<>();
}
public void insert( int val) {
tree.add(val);
}
public int order_of_key( int val) {
int count = 0 ;
for (Integer integer : tree) {
if (integer < val) {
count++;
}
}
return count;
}
public void erase( int val) {
tree.remove(val);
}
@Override
public int compareTo(Integer o) {
return Integer.compare( this .order_of_key(o), o);
}
} class Main {
static Map<Integer, List<Integer>> adj = new HashMap<>();
static Map<Integer, Integer> ans = new HashMap<>();
static void addEdge( int u, int v) {
adj.computeIfAbsent(u, k -> new LinkedList<>()).add(v);
adj.computeIfAbsent(v, k -> new LinkedList<>()).add(u);
}
static void countSmallerAncestors( int root, int par, ordered_set ancestors) {
ans.put(root, ancestors.order_of_key(root));
ancestors.insert(root);
for (Integer node : adj.get(root)) {
if (node != par) {
countSmallerAncestors(node, root, ancestors);
}
}
ancestors.erase(root);
}
public static void main(String[] args) {
int N = 7 ;
addEdge( 1 , 5 );
addEdge( 1 , 4 );
addEdge( 4 , 6 );
addEdge( 5 , 3 );
addEdge( 5 , 2 );
addEdge( 5 , 7 );
ordered_set ancestors = new ordered_set();
countSmallerAncestors( 1 , - 1 , ancestors);
for ( int i = 1 ; i <= N; i++) {
System.out.print(ans.get(i) + " " );
}
}
} //This code is contributed by shivamsharma215 |
# Python program for the above approach import collections
import functools
# Declaring ordered_set @functools .total_ordering
class ordered_set:
def __init__( self ):
self .tree = collections.defaultdict( set )
def insert( self , val):
self .tree[val] = set ()
def __le__( self , other):
return self .tree.keys() < = other.tree.keys()
def __eq__( self , other):
return self .tree.keys() = = other.tree.keys()
def order_of_key( self , val):
return len ([k for k in self .tree.keys() if k < val])
def erase( self , val):
del self .tree[val]
# Map to store final ans for each node ans = {}
# Function to add an edge # between nodes u and v def addEdge(adj, u, v):
adj[u].append(v)
adj[v].append(u)
# Function to count the number of # ancestors with values smaller # than that of the current node def countSmallerAncestors(adj, root, par, 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 node in adj[root]:
# Avoid cycles
if node ! = par:
countSmallerAncestors(
adj, node,
root, ancestors)
# Remove current node from path
ancestors.erase(root)
# Driver Code if __name__ = = '__main__' :
# Number of nodes in graph
N = 7
# Initialize graph
adj = {i:[] for i in range ( 1 ,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
ancestors = ordered_set()
countSmallerAncestors(adj, 1 , - 1 , ancestors)
for i in range ( 1 , N + 1 ):
print (ans[i], end = ' ' )
# # This code is contributed by Vikram_Shirsat |
const adj = []; const ans = new Map();
// Function to add an edge between nodes u and v function addEdge(u, v) {
adj[u].push(v);
adj[v].push(u);
} // Function to count the number of ancestors with values smaller // than that of the current node function countSmallerAncestors(root, par, ancestors) {
// Map current node to number of smaller valued ancestors
ans.set(root, ancestors.indexOf(root));
// Add current node to path
ancestors.push(root);
for (const node of adj[root]) {
// Avoid cycles
if (node !== par) {
countSmallerAncestors(node, root, ancestors);
}
}
// Remove current node from path
ancestors.pop();
} // Main ( function () {
// Number of nodes in graph
const N = 7;
// Initialize graph
for (let i = 0; i <= N; i++) {
adj[i] = [];
}
// Tree Formation
addEdge(1, 5);
addEdge(1, 4);
addEdge(4, 6);
addEdge(5, 3);
addEdge(5, 2);
addEdge(5, 7);
// Array to store values in path from root to current node in dfs
const ancestors = [];
countSmallerAncestors(1, -1, ancestors);
for (let i = 1; i <= N; i++) {
console.log(ans.get(i));
}
})(); |
using System;
using System.Collections.Generic;
// Declaring ordered_set public class OrderedSet
{ private Dictionary< int , HashSet< int >> tree = new Dictionary< int , HashSet< int >>();
public void Insert( int val)
{
tree[val] = new HashSet< int >();
}
public bool IsSubsetOf(OrderedSet other)
{
return new HashSet< int >(tree.Keys).IsSubsetOf(other.tree.Keys);
}
public int CountSmaller( int val)
{
int count = 0;
foreach ( int k in tree.Keys)
{
if (k < val)
{
count++;
}
}
return count;
}
public void Erase( int val)
{
tree.Remove(val);
}
} public class Program
{ // Map to store final ans for each node
private static Dictionary< int , int > ans = new Dictionary< int , int >();
// Function to add an edge
// between nodes u and v
private static void AddEdge(Dictionary< int , List< int >> adj, int u, int v)
{
adj[u].Add(v);
adj[v].Add(u);
}
// Function to count the number of
// ancestors with values smaller
// than that of the current node
private static void CountSmallerAncestors(Dictionary< int , List< int >> adj, int root, int par, OrderedSet ancestors)
{
// Map current node to
// number of smaller valued ancestors
ans[root] = ancestors.CountSmaller(root);
// Add current node to path
ancestors.Insert(root);
foreach ( int node in adj[root])
{
// Avoid cycles
if (node != par)
{
CountSmallerAncestors(adj, node, root, ancestors);
}
}
// Remove current node from path
ancestors.Erase(root);
}
// Driver Code
public static void Main()
{
// Number of nodes in graph
int N = 7;
// Initialize graph
Dictionary< int , List< int >> adj = new Dictionary< int , List< int >>();
for ( int i = 1; i <= N; i++)
{
adj[i] = new List< int >();
}
// 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
OrderedSet ancestors = new OrderedSet();
CountSmallerAncestors(adj, 1, -1, ancestors);
for ( int i = 1; i <= N; i++)
{
Console.Write(ans[i] + " " );
}
}
} |
0 1 1 1 1 2 2
Time Complexity: O(N * log(N)).
Auxiliary Space: O(N).