Consider a full Binary Tree where the root of the Tree is colored as Black initially. Each black-colored node will have red children, and red-colored nodes will have black children. You are given two integer arrays Start[] and End[]. Along with Start[] and End[], there is a Query[] array of size Q with the values:
- Interchange: Interchange the color of all nodes, i.e. black nodes into red and red nodes into black.
- Black: Output the number of Black nodes between the nodes Start and End.
- Red: Output the number of Red nodes between the nodes Start and End.
Examples:
Input: Query[] = {“Black”, “Interchange”, “Red”}, Start[] = {1, 0, 3}, End[] = {5, 0, 8}
Output: First Query=2, Third Query=2
Explanation:
- Query[0]=Black, Start[0]=1, End[0] = 5. Means we have to count of total number of Black nodes in the path from node 1 to 5.
- First Query:
- Query[1]=Interchange. Means, we just have to interchange the color of all nodes. No output will be there for this query.
- Second Query:
- Third Query:
- Query[2]=Red, Start[2]=3, End[2]=8. Means we have to count of total number of Red nodes in the path from node 3 to 8.
Input: Query[] = {“Black”, “Interchange”, “Red”}, Start[] = {1, 0, 8}, End[] = {5, 0, 15}
Output: First Query=2, Third Query=3
Explanation: It can be verified that the number of colored nodes in each query will be same as output.
Approach: Implement the idea below to solve the problem
The problem is based on the concept of Lowest Common Ancestor (LCA). Suppose, if two nodes are in different branch like node 9 and node 11, they are child of node 4 and node 5. So, we have to find a common ground for both the nodes which is the LCA (2 for above nodes) .
Therefore, we just need to
- Calculate total number of nodes (Black or Red according to query type) from the root to both the nodes
- Subtract the number of nodes (Black or Red) from root to LCA as these nodes are were counted twice.
- Also, we have to add 1 to the answer if the LCA node has the same color as it was not counted before.
Steps to solve the problem:
- Create a boolean variable rootBlack and mark it initially as true.
- Create a function getBlackNodes(x, y) to return the total number of black nodes between x and y, if root is black.
- Create a function getRedNodes(x, y) to return the total number of red nodes between x and y, if root is black.
-
For each Query[i],
- If (Query[i] == “Interchange”), then rootBlack = !rootBlack
-
Else If (Query[i] == “Black”)
- If root is black, it means that we currently have the original binary tree, so return getBlackNodes(start[i], end[i])
- else if root is not black, it means that we currently have the interchanged binary tree, so return getRedNodes(start[i], end[i])
-
Else
- If root is black, it means that we currently have the original binary tree, so return getRedNodes(start[i], end[i])
- else if root is not black, it means that we currently have the interchanged binary tree, so return getBlackNodes(start[i], end[i])
Code to implement the approach:
#include <iostream> #include <cmath> using namespace std;
// Function to find the Lowest Common Ancestor (LCA) of two nodes long findLca( long x, long y) {
while (x != y) {
if (x > y)
x /= 2;
else if (y > x)
y /= 2;
}
return x;
} // Function to calculate the height of a node in the tree long height( long n) {
return (log2(n) + 1);
} // Function to calculate the black height of a node long blackHeight( long n) {
return (height(n) + 1) / 2;
} // Function to calculate the red height of a node long redHeight( long n) {
return height(n) / 2;
} // Function to calculate the number of black nodes between two nodes long getBlackNodes( long x, long y) {
long lca = findLca(x, y);
long ans = blackHeight(x) + blackHeight(y) - 2 * blackHeight(height(lca));
return (height(lca) % 2 == 1) ? ans + 1 : ans;
} // Function to calculate the number of red nodes between two nodes long getRedNodes( long x, long y) {
long lca = findLca(x, y);
long ans = redHeight(x) + redHeight(y) - 2 * redHeight(lca);
return (height(lca) % 2 == 0) ? ans + 1 : ans;
} // Function to process queries and print the results void Function(string Query[], int start[], int end[], int n) {
bool rootBlack = true ;
for ( int i = 0; i < n; i++) {
long ans = 0;
if (Query[i] == "Interchange" )
rootBlack = !rootBlack;
else if ((rootBlack && Query[i] == "Black" ) || (!rootBlack && Query[i] == "Red" ))
ans = getBlackNodes(start[i], end[i]);
else
ans = getRedNodes(start[i], end[i]);
cout << ans << endl;
}
} int main() {
string Query[] = { "Black" , "Interchange" , "Red" };
int start[] = { 1, 0, 3 };
int end[] = { 5, 0, 8 };
int n = 3;
// Function call
Function(Query, start, end, n);
return 0;
} |
import java.io.*;
import java.lang.*;
import java.util.*;
class Main {
public static void main(String[] args)
throws java.lang.Exception
{
// Inputs
String[] Query = { "Black", "Interchange", "Red" };
int [] start = { 1 , 0 , 3 };
int [] end = { 5 , 0 , 8 };
// Function call
Function(Query, start, end);
}
// Method to print output of query asked
public static void Function(String[] Query, int [] start,
int [] end)
{
// Initially root Black is marked
// as true
boolean rootBlack = true ;
// Loop for processing queries
for ( int i = 0 ; i < Query.length; i++) {
long ans = 0 ;
if (Query[i].equals("Interchange"))
rootBlack = !rootBlack;
// Root is black and we need to count
// the number of black nodes or Root
// is red and we need to count the
// number of red nodes
else if ((rootBlack && Query[i].equals("Black"))
|| (!rootBlack
&& Query[i].equals("Red")))
ans = getBlackNodes(start[i], end[i]);
// Root is black and we need to count
// the number of red nodes or Root is
// red and we need to count the number
// of black nodes
else
ans = getRedNodes(start[i], end[i]);
System.out.println(ans);
}
}
// Function to return the LCA of
// start and end
static long findLca( long x, long y)
{
while (x != y) {
if (x > y)
x /= 2 ;
else if (y > x)
y /= 2 ;
}
return x;
}
// Function to return the black height of n
static long blackHeight( long n)
{
return (height(n) + 1 ) / 2 ;
}
// Function to return the red height of n
static long redHeight( long n) { return height(n) / 2 ; }
// Function to return the height
static long height( long n)
{
return ( long )(Math.log(n) / Math.log( 2 )) + 1 ;
}
// Static function to return black nodes
// between 2 nodes
static long getBlackNodes( long x, long y)
{
long lca = findLca(x, y);
long ans = blackHeight(x) + blackHeight(y)
- 2 * blackHeight(height(lca));
return (height(lca) % 2 == 1 ) ? ans + 1 : ans;
}
// Static function to return red nodes
// between 2 nodes
static long getRedNodes( long x, long y)
{
long lca = findLca(x, y);
long ans = redHeight(x) + redHeight(y)
- 2 * redHeight(lca);
return (height(lca) % 2 == 0 ) ? ans + 1 : ans;
}
} |
# Python Code import math
# Function to find the Lowest Common Ancestor (LCA) of two nodes def find_lca(x, y):
while x ! = y:
if x > y:
x / / = 2
elif y > x:
y / / = 2
return x
# Function to calculate the height of a node in the tree def height(n):
return int (math.log2(n) + 1 )
# Function to calculate the black height of a node def black_height(n):
return (height(n) + 1 ) / / 2
# Function to calculate the red height of a node def red_height(n):
return height(n) / / 2
# Function to calculate the number of black nodes between two nodes def get_black_nodes(x, y):
lca = find_lca(x, y)
ans = black_height(x) + black_height(y) - 2 * black_height(height(lca))
return ans + 1 if height(lca) % 2 = = 1 else ans
# Function to calculate the number of red nodes between two nodes def get_red_nodes(x, y):
lca = find_lca(x, y)
ans = red_height(x) + red_height(y) - 2 * red_height(lca)
return ans + 1 if height(lca) % 2 = = 0 else ans
# Function to process queries and print the results def function(query, start, end, n):
root_black = True
for i in range (n):
ans = 0
if query[i] = = "Interchange" :
root_black = not root_black
elif (root_black and query[i] = = "Black" ) or ( not root_black and query[i] = = "Red" ):
ans = get_black_nodes(start[i], end[i])
else :
ans = get_red_nodes(start[i], end[i])
print (ans)
if __name__ = = "__main__" :
query = [ "Black" , "Interchange" , "Red" ]
start = [ 1 , 0 , 3 ]
end = [ 5 , 0 , 8 ]
n = 3
# Function call
function(query, start, end, n)
# This code is contributed by guptapratik |
// C# Implementation using System;
namespace LCA
{ class Program
{
// Function to find the Lowest Common Ancestor (LCA) of two nodes
static long FindLca( long x, long y)
{
while (x != y)
{
if (x > y)
x /= 2;
else if (y > x)
y /= 2;
}
return x;
}
// Function to calculate the height of a node in the tree
static long Height( long n)
{
return ( long )(Math.Log(n, 2) + 1);
}
// Function to calculate the black height of a node
static long BlackHeight( long n)
{
return (Height(n) + 1) / 2;
}
// Function to calculate the red height of a node
static long RedHeight( long n)
{
return Height(n) / 2;
}
// Function to calculate the number of black nodes between two nodes
static long GetBlackNodes( long x, long y)
{
long lca = FindLca(x, y);
long ans = BlackHeight(x) + BlackHeight(y) - 2 * BlackHeight(Height(lca));
return (Height(lca) % 2 == 1) ? ans + 1 : ans;
}
// Function to calculate the number of red nodes between two nodes
static long GetRedNodes( long x, long y)
{
long lca = FindLca(x, y);
long ans = RedHeight(x) + RedHeight(y) - 2 * RedHeight(lca);
return (Height(lca) % 2 == 0) ? ans + 1 : ans;
}
// Function to process queries and print the results
static void Function( string [] query, int [] start, int [] end, int n)
{
bool rootBlack = true ;
for ( int i = 0; i < n; i++)
{
long ans = 0;
if (query[i] == "Interchange" )
rootBlack = !rootBlack;
else if ((rootBlack && query[i] == "Black" ) || (!rootBlack && query[i] == "Red" ))
ans = GetBlackNodes(start[i], end[i]);
else
ans = GetRedNodes(start[i], end[i]);
Console.WriteLine(ans);
}
}
static void Main( string [] args)
{
string [] query = { "Black" , "Interchange" , "Red" };
int [] start = { 1, 0, 3 };
int [] end = { 5, 0, 8 };
int n = 3;
// Function call
Function(query, start, end, n);
}
}
} // This code is contributed by Sakshi |
function find(x, y) {
while (x !== y) {
if (x > y)
x = Math.floor(x / 2);
else if (y > x)
y = Math.floor(y / 2);
}
return x;
} // Function to calculate the height of // node in the tree function height(n) {
return Math.floor(Math.log2(n) + 1);
} // Function to calculate the black height of node function blackHeight(n) {
return Math.floor((height(n) + 1) / 2);
} // Function to calculate the red height of node function redHeight(n) {
return Math.floor(height(n) / 2);
} // Function to calculate the number of the black nodes between two nodes function getBlackNodes(x, y) {
const lca = find(x, y);
let ans = blackHeight(x) + blackHeight(y) - 2 * blackHeight(height(lca));
return (height(lca) % 2 === 1) ? ans + 1 : ans;
} // Function to calculate the number of the red nodes between two nodes function getRedNodes(x, y) {
const lca = find(x, y);
let ans = redHeight(x) + redHeight(y) - 2 * redHeight(lca);
return (height(lca) % 2 === 0) ? ans + 1 : ans;
} // Function to process queries and print the results function GFG(queries, start, end) {
let rootBlack = true ;
for (let i = 0; i < queries.length; i++) {
let ans = 0;
if (queries[i] === "Interchange" )
rootBlack = !rootBlack;
else if ((rootBlack && queries[i] === "Black" ) || (!rootBlack && queries[i] === "Red" ))
ans = getBlackNodes(start[i], end[i]);
else
ans = getRedNodes(start[i], end[i]);
console.log(ans);
}
} // Main function function main() {
const queries = [ "Black" , "Interchange" , "Red" ];
const start = [1, 0, 3];
const end = [5, 0, 8];
const n = 3;
// Function call
GFG(queries, start, end, n);
} // Call the main function main(); |
2 0 2
Time Complexity: O(Query.length * (log(x) + log(y)), where x and y are the values of start and end array
Auxiliary Space: O(1)