Open In App

Count of ancestors with smaller value for each node of an N-ary Tree

Last Updated : 27 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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  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.

 

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] + " ");
        }
    }
}


Output:

0 1 1 1 1 2 2

Time Complexity: O(N * log(N)).
Auxiliary Space:  O(N).



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads