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++
// 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
//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 |
Python3
# 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 |
Javascript
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)); } })(); |
C#
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).
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!