Open In App

Find parents that are K level above given node for Q queries

Last Updated : 19 Dec, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Given a tree with N nodes where node 1 is the root, the task is to solve the queries of form {u, k} and find the parent that is k level above the node u.

Note: If the parent is not available then return -1.

Examples:

Input: N = 5 Q = 3, queries = {{4, 1}, {4, 2}, {4, 3}}

Example of the tree

Example of the tree

Output: 3, 1, -1
Explanation: The node 4 is itself in the 3rd level. So there is no node which is 3 level above it.

Approach: The basic idea is as follows

For each store its parents and how much level it is above from that node in a 2D array. 

Follow the below illustration how to build the array.

How to build the 2D array:

  • We can use the concept of a sparse table. 
  • Simply we can store the parent of each node one level up then we can store parents at 2 level up, then 4 level up and recursively we can store the parents upto the root.

Lets say the 2D array is par[][] where par[i][j] will store 2i level up parent of node j. So for the example tree, the 0th row will look like the following.

 

Suppose we want to find the 2 level-up parent of 4, then, we know 1 level up to node 4 is node 3 and 1 level up to node 3 is node 1. So the distance between node 1 and 3 is 1 and node 3 and node 4 is 1. So the total distance between node 1 and 4 would be 2. So we can say that

x = par[i – 1][j]
par[i][j] = par[i-1][x]

We can take help of bits to calculate this efficiently as K can be represented as sum of powers of 2. Let’s say K = 11 so K = 1+2+8. We can simply do it like

  • lets x = 1st parent of j
  • let y = 2 level up parent of x
  • let z = 8 level up parent of y

So our final answer would be z

Follow the steps mentioned below to implement the idea:

  • Initially build the 2D array as shown above for all the nodes of the tree.
  • This can be done using a single DFS.
  • Then for each query, we can find the parent in O(log K) time using the above lookup.

Below is the implementation of the above approach.

C++




// C++ code to implement the idea
 
#include <bits/stdc++.h>
using namespace std;
 
// Structure of a tree node
struct Node {
    int val;
    Node *left, *right;
    Node(int x)
    {
        val = x;
        left = right = NULL;
    }
};
 
// Function to fill the 0th level parent of any node
void dfs(Node* cur, Node* parent, vector<vector<int> >& par)
{
    if (cur == NULL)
        return;
    par[0][cur->val] = parent->val;
    dfs(cur->left, cur, par);
    dfs(cur->right, cur, par);
}
 
// Function to calculate k level up parent.
int findKlevelup(int u, int k, vector<vector<int> >& par)
{
    for (int i = 0; i < 19; i++) {
        if ((k >> i) & 1)
            u = par[i][u];
    }
    return (u ? u : -1);
}
 
// Function to solve the provided queries and
// find the respectie parent
void solve(int n, int q, vector<vector<int> >& queries,
           Node* root)
{
    vector<vector<int> > par(20, vector<int>(n, 0));
    par[0][root->val] = 0;
    dfs(root->left, root, par);
    dfs(root->right, root, par);
 
    // Create the parent array
    for (int i = 1; i <= 18; i++) {
        for (int j = 1; j <= n; j++)
            par[i][j] = par[i - 1][par[i - 1][j]];
    }
 
    // Loop to solve the queries
    for (int i = 0; i < q; i++) {
        int u, k;
        u = queries[i][0];
        k = queries[i][1];
 
        // Function to calculate for k level
        // up parent
        int ans = findKlevelup(u, k, par);
        cout << ans << " ";
    }
}
 
// Driver code
int main()
{
    int N = 5;
    int Q = 3;
 
    // Form the binary tree
    Node* root = new Node(1);
    root->left = new Node(2);
    root->right = new Node(3);
    root->right->left = new Node(4);
    root->right->right = new Node(5);
 
    vector<vector<int> > queries;
    queries = { { 4, 1 }, { 4, 2 }, { 4, 3 } };
 
    // Function call
    solve(N, Q, queries, root);
 
    return 0;
}


Java




// Java code to implement the idea
class GFG{
 
  // Structure of a tree node
  static class Node {
    int val;
    Node left, right;
    Node(int x)
    {
      val = x;
      left = right = null;
    }
  };
 
  // Function to fill the 0th level parent of any node
  static void dfs(Node cur, Node parent, int[][]par)
  {
    if (cur == null)
      return;
    par[0][cur.val] = parent.val;
    dfs(cur.left, cur, par);
    dfs(cur.right, cur, par);
  }
 
  // Function to calculate k level up parent.
  static int findKlevelup(int u, int k, int[][]par)
  {
    for (int i = 0; i < 19; i++) {
      if (((k >> i) & 1) > 0)
        u = par[i][u];
    }
    return (u > 0 ? u : -1);
  }
 
  // Function to solve the provded queries and
  // find the respectie parent
  static void solve(int n, int q, int [][]queries,
                    Node root)
  {
 
    int [][] par = new int[20][20];
 
    par[0][root.val] = 0;
    dfs(root.left, root, par);
    dfs(root.right, root, par);
 
    // Create the parent array
    for (int i = 1; i <= 18; i++) {
      for (int j = 1; j <= n; j++)
        par[i][j] = par[i - 1][par[i - 1][j]];
    }
 
    // Loop to solve the queries
    for (int i = 0; i < q; i++) {
      int u, k;
      u = queries[i][0];
      k = queries[i][1];
 
      // Function to calculate for k level
      // up parent
      int ans = findKlevelup(u, k, par);
      System.out.print(ans + " ");
    }
  }
 
  // Driver code
  public static void main(String args[])
  {
    int N = 5;
    int Q = 3;
 
    // Form the binary tree
    Node root = new Node(1);
    root.left = new Node(2);
    root.right = new Node(3);
    root.right.left = new Node(4);
    root.right.right = new Node(5);
 
    int [][] queries = { { 4, 1 }, { 4, 2 }, { 4, 3 } };
 
    // Function call
    solve(N, Q, queries, root);
  }
}
 
// This code is contributed By Saurabh Jaiswal


Python3




# Python code to implement the idea
 
# Structure of a tree node
class Node:
    def __init__(self, x):
        self.left = None
        self.right = None
        self.val = x
 
# Function to fill the 0th level parent of any node.
def dfs(cur, parent, par):
    if(cur == None):
        return
    par[0][cur.val] = parent.val
    dfs(cur.left, cur, par)
    dfs(cur.right, cur, par)
 
# Function to calculate k level up parent.
def findKlevelup(u, k, par):
    for i in range(19):
        if(((k >> i) & 1) > 0):
            u = par[i][u]
 
    return u if u > 0 else -1
 
# Function to solve the provided queries
# and find the respective parent
def solve(n, q, queries, root):
    par = [[0 for x in range(20)] for y in range(20)]
 
    par[0][root.val] = 0
    dfs(root.left, root, par)
    dfs(root.right, root, par)
 
    # create the parent array
    for i in range(1, 19):
        for j in range(1, n+1):
            par[i][j] = par[i-1][par[i-1][j]]
 
    # loop to solve the queries
    for i in range(q):
        u = queries[i][0]
        k = queries[i][1]
 
        # Function to calculate for k level up parent
        ans = findKlevelup(u, k, par)
        print(ans, end=" ")
 
 
N, Q = 5, 3
 
# Form the binary tree
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.right.left = Node(4)
root.right.right = Node(5)
 
queries = [[4, 1], [4, 2], [4, 3]]
 
# Function call
solve(N, Q, queries, root)
 
# This code is contributed By lokesh.


C#




// C# code to implement the idea
using System;
public class GFG {
 
  // Structure of a tree node
  class Node {
    public int val;
    public Node left, right;
    public Node(int x)
    {
      val = x;
      left = right = null;
    }
  }
 
  // Function to fill the 0th level parent of any node
  static void dfs(Node cur, Node parent, int[, ] par)
  {
    if (cur == null)
      return;
    par[0, cur.val] = parent.val;
    dfs(cur.left, cur, par);
    dfs(cur.right, cur, par);
  }
 
  // Function to calculate k level up parent.
  static int findKlevelup(int u, int k, int[, ] par)
  {
    for (int i = 0; i < 19; i++) {
      if (((k >> i) & 1) > 0)
        u = par[i, u];
    }
    return (u > 0 ? u : -1);
  }
 
  // Function to solve the provded queries and
  // find the respectie parent
  static void solve(int n, int q, int[, ] queries,
                    Node root)
  {
 
    int[, ] par = new int[20, 20];
 
    par[0, root.val] = 0;
    dfs(root.left, root, par);
    dfs(root.right, root, par);
 
    // Create the parent array
    for (int i = 1; i <= 18; i++) {
      for (int j = 1; j <= n; j++)
        par[i, j] = par[i - 1, par[i - 1, j]];
    }
 
    // Loop to solve the queries
    for (int i = 0; i < q; i++) {
      int u, k;
      u = queries[i, 0];
      k = queries[i, 1];
 
      // Function to calculate for k level
      // up parent
      int ans = findKlevelup(u, k, par);
      Console.Write(ans + " ");
    }
  }
 
  static public void Main()
  {
 
    // Code
    int N = 5;
    int Q = 3;
 
    // Form the binary tree
    Node root = new Node(1);
    root.left = new Node(2);
    root.right = new Node(3);
    root.right.left = new Node(4);
    root.right.right = new Node(5);
 
    int[, ] queries = { { 4, 1 }, { 4, 2 }, { 4, 3 } };
 
    // Function call
    solve(N, Q, queries, root);
  }
}
 
// This code is contributed By lokeshmvs21.


Javascript




       // JavaScript code for the above approach
 
       // Structure of a tree node
       class Node {
           constructor(item) {
               this.val = item;
               this.left = this.right = null;
           }
       }
 
       // Function to fill the 0th level parent of any node
       function dfs(cur, parent, par) {
           if (cur == null)
               return;
           par[0][cur.val] = parent.val;
           dfs(cur.left, cur, par);
           dfs(cur.right, cur, par);
       }
 
       // Function to calculate k level up parent.
       function findKlevelup(u, k, par) {
           for (let i = 0; i < 19; i++) {
               if ((k >> i) & 1)
                   u = par[i][u];
           }
           return (u ? u : -1);
       }
 
       // Function to solve the provded queries and
       // find the respectie parent
       function solve(n, q, queries,
           root) {
           let par = new Array(20);
           for (let i = 0; i < par.length; i++) {
               par[i] = new Array(n).fill(0);
           }
           par[0][root.val] = 0;
           dfs(root.left, root, par);
           dfs(root.right, root, par);
 
           // Create the parent array
           for (let i = 1; i <= 18; i++) {
               for (let j = 1; j <= n; j++)
                   par[i][j] = par[i - 1][par[i - 1][j]];
           }
 
           // Loop to solve the queries
           for (let i = 0; i < q; i++) {
               let u, k;
               u = queries[i][0];
               k = queries[i][1];
 
               // Function to calculate for k level
               // up parent
               let ans = findKlevelup(u, k, par);
              console.log(ans + " ");
           }
       }
 
       // Driver code
 
       let N = 5;
       let Q = 3;
 
       // Form the binary tree
       let root = new Node(1);
       root.left = new Node(2);
       root.right = new Node(3);
       root.right.left = new Node(4);
       root.right.right = new Node(5);
 
       let queries;
       queries = [[4, 1], [4, 2], [4, 3]];
 
       // Function call
       solve(N, Q, queries, root);
 
// This code is contributed by Potta Lokesh


Output

3 1 -1 

Time Complexity: O(N+ Q*LogK)
Auxiliary Space: O(N) 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads