Given an integer N and an N-ary Tree of the following form:
- Every node is numbered sequentially, starting from 1, till the last level, which contains the node N.
- The nodes at every odd level contains 2 children and nodes at every even level contains 4 children.
The task is to print the path from the root node to the node N.
Examples:
Input: N = 14
Output: 1 2 5 14
Explanation: The path from node 1 to node 14 is 1 – > 2 – > 5 – > 14.Input: N = 11
Output: 1 3 11
Explanation: The path from node 1 to node 11 is 1 – > 3 – > 11.
Approach: Follow the steps below to solve the problem:
- Initialize an array to store the number of nodes present in each level of the Tree, i.e. {1, 2, 8, 16, 64, 128 ….} and store it.
- Calculate prefix sum of the array i.e. {1 3 11 27 91 219 …….}
- Find the index ind in the prefix sum array which exceeds or is equal to N using lower_bound(). Therefore, ind indicates the number of levels that need to be traversed to reach node N.
- Initialize a variable say, temp = N and an array path[] to store the nodes from root to N.
- Decrement ind until it is less than or equal to 1 and keep updating val = temp – prefix[ind – 1].
- Update temp = prefix[ind – 2] + (val + 1) / 2 if ind is odd.
- Otherwise, update temp = prefix[ind – 2] + (val + 3) / 4 if ind is even.
- Append temp into the path[] array.
- Finally, print the array, path[].
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
typedef long long ll;
// Function to find the path // from root to N void PrintPathNodes(ll N)
{ // Stores the number of
// nodes at (i + 1)-th level
vector<ll> arr;
arr.push_back(1);
// Stores the number of nodes
ll k = 1;
// Stores if the current
// level is even or odd
bool flag = true ;
while (k < N) {
// If level is odd
if (flag == true ) {
k *= 2;
flag = false ;
}
// If level is even
else {
k *= 4;
flag = true ;
}
// If level with
// node N is reached
if (k > N) {
break ;
}
// Push into vector
arr.push_back(k);
}
ll len = arr.size();
vector<ll> prefix(len);
prefix[0] = 1;
// Compute prefix sums of count
// of nodes in each level
for (ll i = 1; i < len; ++i) {
prefix[i] = arr[i] + prefix[i - 1];
}
vector<ll>::iterator it
= lower_bound(prefix.begin(),
prefix.end(), N);
// Stores the level in which
// node N s present
ll ind = it - prefix.begin();
ll temp = N;
// Store path
vector< int > path;
path.push_back(N);
while (ind > 1) {
ll val = temp - prefix[ind - 1];
if (ind % 2 != 0) {
temp = prefix[ind - 2]
+ (val + 1) / 2;
}
else {
temp = prefix[ind - 2]
+ (val + 3) / 4;
}
--ind;
// Insert temp into path
path.push_back(temp);
}
if (N != 1)
path.push_back(1);
// Print path
for ( int i = path.size() - 1;
i >= 0; i--) {
cout << path[i] << " " ;
}
} // Driver Code int main()
{ ll N = 14;
// Function Call
PrintPathNodes(N);
return 0;
} |
Java
// Java program for the above approach import java.util.*;
public class Main {
// Function to find the path
// from root to N
static void PrintPathNodes( long N)
{
// Stores the number of
// nodes at (i + 1)-th level
ArrayList<Long> arr = new ArrayList<>();
arr.add(( long ) 1 );
// Stores the number of nodes
long k = 1 ;
// Stores if the current
// level is even or odd
boolean flag = true ;
while (k < N) {
// If level is odd
if (flag == true ) {
k *= 2 ;
flag = false ;
}
// If level is even
else {
k *= 4 ;
flag = true ;
}
// If level with
// node N is reached
if (k > N) {
break ;
}
// Push into array
arr.add(k);
}
long len = arr.size();
ArrayList<Long> prefix = new ArrayList<>();
prefix.add(( long ) 1 );
// Compute prefix sums of count
// of nodes in each level
for ( long i = 1 ; i < len; ++i) {
prefix.add(arr.get(( int )i) + prefix.get(( int )i - 1 ));
}
int ind = Collections.binarySearch(prefix, N);
// Stores the level in which
// node N s present
if (ind < 0 ) {
ind = -ind - 1 ;
}
long temp = N;
// Store path
ArrayList<Long> path = new ArrayList<>();
path.add(N);
while (ind > 1 ) {
long val = temp - prefix.get(( int )ind - 1 );
if (ind % 2 != 0 ) {
temp = prefix.get(( int )ind - 2 )
+ (val + 1 ) / 2 ;
}
else {
temp = prefix.get(( int )ind - 2 )
+ (val + 3 ) / 4 ;
}
--ind;
// Insert temp into path
path.add(temp);
}
if (N != 1 )
path.add(( long ) 1 );
// Print path
for ( int i = path.size() - 1 ;
i >= 0 ; i--) {
System.out.print(path.get(i) + " " );
}
}
// Driver Code
public static void main(String[] args)
{
long N = 14 ;
// Function Call
PrintPathNodes(N);
}
} // This code is contributed by princekumaras |
Python3
# Python3 program for the above approach from bisect import bisect_left
# Function to find the path # from root to N def PrintPathNodes(N):
# Stores the number of
# nodes at (i + 1)-th level
arr = []
arr.append( 1 )
# Stores the number of nodes
k = 1
# Stores if the current
# level is even or odd
flag = True
while (k < N):
# If level is odd
if (flag = = True ):
k * = 2
flag = False
# If level is even
else :
k * = 4
flag = True
# If level with
# node N is reached
if (k > N):
break
# Push into vector
arr.append(k)
lenn = len (arr)
prefix = [ 0 ] * (lenn)
prefix[ 0 ] = 1
# Compute prefix sums of count
# of nodes in each level
for i in range ( 1 ,lenn):
prefix[i] = arr[i] + prefix[i - 1 ]
it = bisect_left(prefix, N)
# Stores the level in which
# node N s present
ind = it
temp = N
# Store path
path = []
path.append(N)
while (ind > 1 ):
val = temp - prefix[ind - 1 ]
if (ind % 2 ! = 0 ):
temp = prefix[ind - 2 ] + (val + 1 ) / / 2
else :
temp = prefix[ind - 2 ] + (val + 3 ) / / 4
ind - = 1
# Insert temp into path
path.append(temp)
if (N ! = 1 ):
path.append( 1 )
# Print path
for i in range ( len (path) - 1 , - 1 , - 1 ):
print (path[i], end = " " )
# Driver Code if __name__ = = '__main__' :
N = 14
# Function Call
PrintPathNodes(N)
# This code is contributed by mohit kumar 29
|
C#
// C# program for the above approach using System;
using System.Collections.Generic;
class GFG
{ // Function to find the path
// from root to N
static void PrintPathNodes( long N)
{
// Stores the number of
// nodes at (i + 1)-th level
List< long > arr = new List< long >();
arr.Add(( long )1);
// Stores the number of nodes
long k = 1;
// Stores if the current
// level is even or odd
bool flag = true ;
while (k < N) {
// If level is odd
if (flag == true ) {
k *= 2;
flag = false ;
}
// If level is even
else {
k *= 4;
flag = true ;
}
// If level with
// node N is reached
if (k > N) {
break ;
}
// Push into array
arr.Add(k);
}
long len = arr.Count;
List< long > prefix = new List< long >();
prefix.Add(( long )1);
// Compute prefix sums of count
// of nodes in each level
for ( long i = 1; i < len; ++i) {
prefix.Add(arr[( int )i] + prefix[( int )i - 1]);
}
int ind = prefix.BinarySearch(N);
// Stores the level in which
// node N s present
if (ind < 0) {
ind = -ind - 1;
}
long temp = N;
// Store path
List< long > path = new List< long >();
path.Add(N);
while (ind > 1) {
long val = temp - prefix[( int )ind - 1];
if (ind % 2 != 0) {
temp = prefix[( int )ind - 2] + (val + 1) / 2;
}
else {
temp = prefix[( int )ind - 2] + (val + 3) / 4;
}
--ind;
// Insert temp into path
path.Add(temp);
}
if (N != 1)
path.Add(( long )1);
// Print path
for ( int i = path.Count - 1; i >= 0; i--) {
Console.Write(path[i] + " " );
}
}
// Driver Code
public static void Main( string [] args)
{
long N = 14;
// Function Call
PrintPathNodes(N);
}
} // This code is contributed by phasing17 |
Javascript
// JavaScript program for the above approach function bisect_left(a, x, lo = 0, hi = a.length) {
while (lo < hi) {
let mid = Math.floor((lo + hi) / 2);
if (a[mid] < x) {
lo = mid + 1;
} else {
hi = mid;
}
}
return lo;
} // Function to find the path // from root to N function PrintPathNodes(N) {
// Stores the number of
// nodes at (i + 1)-th level
let arr = [];
arr.push(1);
// Stores the number of nodes
let k = 1;
// Stores if the current
// level is even or odd
let flag = true ;
while (k < N) {
// If level is odd
if (flag === true ) {
k *= 2;
flag = false ;
}
// If level is even
else {
k *= 4;
flag = true ;
}
// If level with
// node N is reached
if (k > N) {
break ;
}
// Push into array
arr.push(k);
}
let lenn = arr.length;
let prefix = new Array(lenn).fill(0);
prefix[0] = 1;
// Compute prefix sums of count
// of nodes in each level
for (let i = 1; i < lenn; i++) {
prefix[i] = arr[i] + prefix[i - 1];
}
let it = bisect_left(prefix, N);
// Stores the level in which
// node N s present
let ind = it;
let temp = N;
// Store path
let path = [];
path.push(N);
while (ind > 1) {
let val = temp - prefix[ind - 1];
if (ind % 2 !== 0) {
temp = prefix[ind - 2] + Math.floor((val + 1) / 2);
} else {
temp = prefix[ind - 2] + Math.floor((val + 3) / 4);
}
ind -= 1;
// Insert temp into path
path.push(temp);
}
if (N !== 1) {
path.push(1);
}
// Print path
for (let i = path.length - 1; i >= 0; i--) {
process.stdout.write(path[i] + " " );
}
} // Driver Code let N = 14; // Function Call PrintPathNodes(N); // This code is contributed by phasing17 |
Output:
1 2 5 14
Time Complexity: O(log(N))
Auxiliary Space: O(log(N))