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}}
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++ 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 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 |
# 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# 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 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 |
3 1 -1
Time Complexity: O(N+ Q*LogK)
Auxiliary Space: O(N)