Related Articles

# Queries to check if the path between two nodes in a tree is a palindrome

• Difficulty Level : Hard
• Last Updated : 24 Jun, 2021

Given a tree with N nodes and N – 1 edges. Each edge of the tree is labeled by a string of lowercase english alphabets. You are given Q queries. In each query you are given two node x and y. For the path between x to y, the task is to check if it is possible to make a new palindrome string which use all the characters in the path from node x to node y. Note that you can use the characters in any order you like and root node is always 1.
Examples:

```Input:
1
(bbc)/   \(ac)
2     3
Q[][] = {{1, 2}, {2, 3}, {3, 1}, {3, 3}}
Output:
Yes
Yes
No
Yes
Query 1: "bbc" can be arranged into "bcb"
which is a palindrome.
Query 2: "bbcac" -> "bcacb"
Query 3: No permutation of "ac" is palindrome.
Query 4: "acac" -> "acca"

Input:
1
/    |     \
/(ab)  |(bca)  \(bc)
2        3         4
\(ab)
5
Q[][] = {{1, 5}, {4, 5}, {5, 4}}
Output:
Yes
No
No```

Approach: For each query, the character count for path x to y has to be calculated. After finding the characters count, it can be easily checked whether the characters will form a palindrome or not using the approach discussed in this article.
Steps to get the character count for path x to y.

1. Set the initial character count for each node.
2. Update character count of the root’s child node and then repeat the same process for its child node.
3. Find LCA (Lowest Common Ancestor) of x and y.
4. Calculate character count for path x to y with the following step:
For each character charCount[i] = (xNodeCharCount[i] – lcaNodeCharCount[i]) + (yNodeCharCount[i] – lcaNodeCharCount[i])

5. Now check whether a palindrome can be formed with the current count of characters.

Below is the implementation of the above approach:

## C++

 `// C++ implementation of the approach``#include ``using` `namespace` `std;` `const` `int` `MAX_SIZE = 100005, MAX_CHAR = 26;``int` `nodeCharactersCount[MAX_SIZE][MAX_CHAR];` `vector<``int``> tree[MAX_SIZE];` `// Function that returns true if a palindromic``// string can be formed using the given characters``bool` `canFormPalindrome(``int``* charArray)``{` `    ``// Count odd occurring characters``    ``int` `oddCount = 0;``    ``for` `(``int` `i = 0; i < MAX_CHAR; i++) {``        ``if` `(charArray[i] % 2 == 1)``            ``oddCount++;``    ``}``    ``// Return false if odd count is more than 1,``    ``if` `(oddCount >= 2)``        ``return` `false``;``    ``else``        ``return` `true``;``}` `// Find to find the Lowest Common``// Ancestor in the tree``int` `LCA(``int` `currentNode, ``int` `x, ``int` `y)``{``    ``// Base case``    ``if` `(currentNode == x)``        ``return` `x;` `    ``// Base case``    ``if` `(currentNode == y)``        ``return` `y;``    ``int` `xLca, yLca;` `    ``// Initially value -1 denotes that``    ``// we need to find the ancestor``    ``xLca = yLca = -1;` `    ``// -1 denotes that we need to find the lca``    ``// for x and y, values other than x and y``    ``// will be the LCA of x and y``    ``int` `gotLca = -1;` `    ``// Iterating in the child``    ``// substree of the currentNode``    ``for` `(``int` `l = 0; l < tree[currentNode].size(); l++) {` `        ``// Next node that will be checked``        ``int` `nextNode = tree[currentNode][l];` `        ``// Look for the next child subtree``        ``int` `out_ = LCA(nextNode, x, y);` `        ``if` `(out_ == x)``            ``xLca = out_;``        ``if` `(out_ == y)``            ``yLca = out_;` `        ``// Both the nodes exist in the different``        ``// subtrees, in this case parent node``        ``// will be the lca``        ``if` `(xLca != -1 and yLca != -1)``            ``return` `currentNode;` `        ``// Handle the cases where LCA is already``        ``// calculated or both x and y are present``        ``// in the same subtree``        ``if` `(out_ != -1)``            ``gotLca = out_;``    ``}``    ``return` `gotLca;``}` `// Function to calculate the character count for``// each path from node i to 1 (root node)``void` `buildTree(``int` `i)``{``    ``for` `(``int` `l = 0; l < tree[i].size(); l++) {` `        ``int` `nextNode = tree[i][l];``        ``for` `(``int` `j = 0; j < MAX_CHAR; j++) {` `            ``// Updating the character count``            ``// for each node``            ``nodeCharactersCount[nextNode][j]``                ``+= nodeCharactersCount[i][j];``        ``}` `        ``// Look for the child subtree``        ``buildTree(nextNode);``    ``}``}` `// Function that returns true if a palindromic path``// is possible between the nodes x and y``bool` `canFormPalindromicPath(``int` `x, ``int` `y)``{` `    ``int` `lcaNode;` `    ``// If both x and y are same then``    ``// lca will be the node itself``    ``if` `(x == y)``        ``lcaNode = x;` `    ``// Find the lca of x and y``    ``else``        ``lcaNode = LCA(1, x, y);` `    ``int` `charactersCountFromXtoY[MAX_CHAR] = { 0 };` `    ``// Calculating the character count``    ``// for path node x to y``    ``for` `(``int` `i = 0; i < MAX_CHAR; i++) {``        ``charactersCountFromXtoY[i]``            ``= nodeCharactersCount[x][i]``              ``+ nodeCharactersCount[y][i]``              ``- 2 * nodeCharactersCount[lcaNode][i];``    ``}` `    ``// Checking if we can form the palindrome``    ``// string with the all character count``    ``if` `(canFormPalindrome(charactersCountFromXtoY))``        ``return` `true``;``    ``return` `false``;``}` `// Function to update character count at node v``void` `updateNodeCharactersCount(string str, ``int` `v)``{` `    ``// Updating the character count at node v``    ``for` `(``int` `i = 0; i < str.length(); i++)``        ``nodeCharactersCount[v][str[i] - ``'a'``]++;``}` `// Function to perform the queries``void` `performQueries(vector > queries, ``int` `q)``{``    ``int` `i = 0;``    ``while` `(i < q) {` `        ``int` `x = queries[i];``        ``int` `y = queries[i];` `        ``// If path can be a palindrome``        ``if` `(canFormPalindromicPath(x, y))``            ``cout << ``"Yes\n"``;``        ``else``            ``cout << ``"No\n"``;``        ``i++;``    ``}``}` `// Driver code``int` `main()``{` `    ``// Fill the complete array with 0``    ``memset``(nodeCharactersCount, 0,``           ``sizeof``(nodeCharactersCount));` `    ``// Edge between 1 and 2 labelled "bbc"``    ``tree.push_back(2);``    ``updateNodeCharactersCount(``"bbc"``, 2);` `    ``// Edge between 1 and 3 labelled "ac"``    ``tree.push_back(3);``    ``updateNodeCharactersCount(``"ac"``, 3);` `    ``// Update the character count``    ``// from root to the ith node``    ``buildTree(1);` `    ``vector > queries{ { 1, 2 },``                                  ``{ 2, 3 },``                                  ``{ 3, 1 },``                                  ``{ 3, 3 } };``    ``int` `q = queries.size();` `    ``// Perform the queries``    ``performQueries(queries, q);` `    ``return` `0;``}`

## Java

 `// Java implementation of the approach``import` `java.util.*;` `@SuppressWarnings``(``"unchecked"``)``class` `GFG {` `    ``static` `int` `MAX_SIZE = ``100005``, MAX_CHAR = ``26``;``    ``static` `int``[][] nodeCharactersCount = ``new` `int``[MAX_SIZE][MAX_CHAR];` `    ``static` `Vector[] tree = ``new` `Vector[MAX_SIZE];` `    ``// Function that returns true if a palindromic``    ``// string can be formed using the given characters``    ``static` `boolean` `canFormPalindrome(``int``[] charArray) {` `        ``// Count odd occurring characters``        ``int` `oddCount = ``0``;``        ``for` `(``int` `i = ``0``; i < MAX_CHAR; i++) {``            ``if` `(charArray[i] % ``2` `== ``1``)``                ``oddCount++;``        ``}``        ``// Return false if odd count is more than 1,``        ``if` `(oddCount >= ``2``)``            ``return` `false``;``        ``else``            ``return` `true``;``    ``}` `    ``// Find to find the Lowest Common``    ``// Ancestor in the tree``    ``static` `int` `LCA(``int` `currentNode, ``int` `x, ``int` `y) {` `        ``// Base case``        ``if` `(currentNode == x)``            ``return` `x;` `        ``// Base case``        ``if` `(currentNode == y)``            ``return` `y;``        ``int` `xLca, yLca;` `        ``// Initially value -1 denotes that``        ``// we need to find the ancestor``        ``xLca = yLca = -``1``;` `        ``// -1 denotes that we need to find the lca``        ``// for x and y, values other than x and y``        ``// will be the LCA of x and y``        ``int` `gotLca = -``1``;` `        ``// Iterating in the child``        ``// substree of the currentNode``        ``for` `(``int` `l = ``0``; l < tree[currentNode].size(); l++) {` `            ``// Next node that will be checked``            ``int` `nextNode = tree[currentNode].elementAt(l);` `            ``// Look for the next child subtree``            ``int` `out_ = LCA(nextNode, x, y);` `            ``if` `(out_ == x)``                ``xLca = out_;``            ``if` `(out_ == y)``                ``yLca = out_;` `            ``// Both the nodes exist in the different``            ``// subtrees, in this case parent node``            ``// will be the lca``            ``if` `(xLca != -``1` `&& yLca != -``1``)``                ``return` `currentNode;` `            ``// Handle the cases where LCA is already``            ``// calculated or both x and y are present``            ``// in the same subtree``            ``if` `(out_ != -``1``)``                ``gotLca = out_;``        ``}``        ``return` `gotLca;``    ``}` `    ``// Function to calculate the character count for``    ``// each path from node i to 1 (root node)``    ``static` `void` `buildTree(``int` `i) {``        ``for` `(``int` `l = ``0``; l < tree[i].size(); l++) {` `            ``int` `nextNode = tree[i].elementAt(l);``            ``for` `(``int` `j = ``0``; j < MAX_CHAR; j++) {` `                ``// Updating the character count``                ``// for each node``                ``nodeCharactersCount[nextNode][j] += nodeCharactersCount[i][j];``            ``}` `            ``// Look for the child subtree``            ``buildTree(nextNode);``        ``}``    ``}` `    ``// Function that returns true if a palindromic path``    ``// is possible between the nodes x and y``    ``static` `boolean` `canFormPalindromicPath(``int` `x, ``int` `y) {` `        ``int` `lcaNode;` `        ``// If both x and y are same then``        ``// lca will be the node itself``        ``if` `(x == y)``            ``lcaNode = x;` `        ``// Find the lca of x and y``        ``else``            ``lcaNode = LCA(``1``, x, y);` `        ``int``[] charactersCountFromXtoY = ``new` `int``[MAX_CHAR];``        ``Arrays.fill(charactersCountFromXtoY, ``0``);` `        ``// Calculating the character count``        ``// for path node x to y``        ``for` `(``int` `i = ``0``; i < MAX_CHAR; i++) {``            ``charactersCountFromXtoY[i] = nodeCharactersCount[x][i] +``                                         ``nodeCharactersCount[y][i]``                               ``- ``2` `* nodeCharactersCount[lcaNode][i];``        ``}` `        ``// Checking if we can form the palindrome``        ``// string with the all character count``        ``if` `(canFormPalindrome(charactersCountFromXtoY))``            ``return` `true``;``        ``return` `false``;``    ``}` `    ``// Function to update character count at node v``    ``static` `void` `updateNodeCharactersCount(String str, ``int` `v) {` `        ``// Updating the character count at node v``        ``for` `(``int` `i = ``0``; i < str.length(); i++)``            ``nodeCharactersCount[v][str.charAt(i) - ``'a'``]++;``    ``}` `    ``// Function to perform the queries``    ``static` `void` `performQueries(``int``[][] queries, ``int` `q) {``        ``int` `i = ``0``;``        ``while` `(i < q) {` `            ``int` `x = queries[i][``0``];``            ``int` `y = queries[i][``1``];` `            ``// If path can be a palindrome``            ``if` `(canFormPalindromicPath(x, y))``                ``System.out.println(``"Yes"``);``            ``else``                ``System.out.println(``"No"``);``            ``i++;``        ``}``    ``}` `    ``// Driver Code``    ``public` `static` `void` `main(String[] args) {` `        ``// Fill the complete array with 0``        ``for` `(``int` `i = ``0``; i < MAX_SIZE; i++) {``            ``for` `(``int` `j = ``0``; j < MAX_CHAR; j++) {``                ``nodeCharactersCount[i][j] = ``0``;``            ``}``        ``}``        ``for` `(``int` `i = ``0``; i < MAX_SIZE; i++) {``            ``tree[i] = ``new` `Vector<>();``        ``}` `        ``// Edge between 1 and 2 labelled "bbc"``        ``tree[``1``].add(``2``);``        ``updateNodeCharactersCount(``"bbc"``, ``2``);` `        ``// Edge between 1 and 3 labelled "ac"``        ``tree[``1``].add(``3``);``        ``updateNodeCharactersCount(``"ac"``, ``3``);` `        ``// Update the character count``        ``// from root to the ith node``        ``buildTree(``1``);` `        ``int``[][] queries = { { ``1``, ``2` `}, { ``2``, ``3` `}, { ``3``, ``1` `}, { ``3``, ``3` `} };``        ``int` `q = queries.length;` `        ``// Perform the queries``        ``performQueries(queries, q);``    ``}``}` `// This code is contributed by``// sanjeev2552`

## C#

 `// C# implementation of the approach``using` `System;``using` `System.Collections.Generic;``class` `GFG``{` `  ``static` `int` `MAX_SIZE = 100005, MAX_CHAR = 26;``  ``static` `int``[,] nodecharsCount = ``new` `int``[MAX_SIZE, MAX_CHAR];``  ``static` `List<``int``>[] tree = ``new` `List<``int``>[MAX_SIZE];` `  ``// Function that returns true if a palindromic``  ``// string can be formed using the given characters``  ``static` `bool` `canFormPalindrome(``int``[] charArray)``  ``{` `    ``// Count odd occurring characters``    ``int` `oddCount = 0;``    ``for` `(``int` `i = 0; i < MAX_CHAR; i++)``    ``{``      ``if` `(charArray[i] % 2 == 1)``        ``oddCount++;``    ``}` `    ``// Return false if odd count is more than 1,``    ``if` `(oddCount >= 2)``      ``return` `false``;``    ``else``      ``return` `true``;``  ``}` `  ``// Find to find the Lowest Common``  ``// Ancestor in the tree``  ``static` `int` `LCA(``int` `currentNode, ``int` `x, ``int` `y)``  ``{` `    ``// Base case``    ``if` `(currentNode == x)``      ``return` `x;` `    ``// Base case``    ``if` `(currentNode == y)``      ``return` `y;``    ``int` `xLca, yLca;` `    ``// Initially value -1 denotes that``    ``// we need to find the ancestor``    ``xLca = yLca = -1;` `    ``// -1 denotes that we need to find the lca``    ``// for x and y, values other than x and y``    ``// will be the LCA of x and y``    ``int` `gotLca = -1;` `    ``// Iterating in the child``    ``// substree of the currentNode``    ``for` `(``int` `l = 0; l < tree[currentNode].Count; l++)``    ``{` `      ``// Next node that will be checked``      ``int` `nextNode = tree[currentNode][l];` `      ``// Look for the next child subtree``      ``int` `out_ = LCA(nextNode, x, y);` `      ``if` `(out_ == x)``        ``xLca = out_;``      ``if` `(out_ == y)``        ``yLca = out_;` `      ``// Both the nodes exist in the different``      ``// subtrees, in this case parent node``      ``// will be the lca``      ``if` `(xLca != -1 && yLca != -1)``        ``return` `currentNode;` `      ``// Handle the cases where LCA is already``      ``// calculated or both x and y are present``      ``// in the same subtree``      ``if` `(out_ != -1)``        ``gotLca = out_;``    ``}``    ``return` `gotLca;``  ``}` `  ``// Function to calculate the character count for``  ``// each path from node i to 1 (root node)``  ``static` `void` `buildTree(``int` `i)``  ``{``    ``for` `(``int` `l = 0; l < tree[i].Count; l++)``    ``{``      ``int` `nextNode = tree[i][l];``      ``for` `(``int` `j = 0; j < MAX_CHAR; j++)``      ``{` `        ``// Updating the character count``        ``// for each node``        ``nodecharsCount[nextNode,j] += nodecharsCount[i,j];``      ``}` `      ``// Look for the child subtree``      ``buildTree(nextNode);``    ``}``  ``}` `  ``// Function that returns true if a palindromic path``  ``// is possible between the nodes x and y``  ``static` `bool` `canFormPalindromicPath(``int` `x, ``int` `y)``  ``{``    ``int` `lcaNode;` `    ``// If both x and y are same then``    ``// lca will be the node itself``    ``if` `(x == y)``      ``lcaNode = x;` `    ``// Find the lca of x and y``    ``else``      ``lcaNode = LCA(1, x, y);``    ``int``[] charactersCountFromXtoY = ``new` `int``[MAX_CHAR];` `    ``// Calculating the character count``    ``// for path node x to y``    ``for` `(``int` `i = 0; i < MAX_CHAR; i++)``    ``{``      ``charactersCountFromXtoY[i] = nodecharsCount[x, i] +``        ``nodecharsCount[y, i]``        ``- 2 * nodecharsCount[lcaNode, i];``    ``}` `    ``// Checking if we can form the palindrome``    ``// string with the all character count``    ``if` `(canFormPalindrome(charactersCountFromXtoY))``      ``return` `true``;``    ``return` `false``;``  ``}` `  ``// Function to update character count at node v``  ``static` `void` `updateNodecharsCount(String str, ``int` `v)``  ``{` `    ``// Updating the character count at node v``    ``for` `(``int` `i = 0; i < str.Length; i++)``      ``nodecharsCount[v, str[i] - ``'a'``]++;``  ``}` `  ``// Function to perform the queries``  ``static` `void` `performQueries(``int``[,] queries, ``int` `q) {``    ``int` `i = 0;``    ``while` `(i < q) {` `      ``int` `x = queries[i, 0];``      ``int` `y = queries[i, 1];` `      ``// If path can be a palindrome``      ``if` `(canFormPalindromicPath(x, y))``        ``Console.WriteLine(``"Yes"``);``      ``else``        ``Console.WriteLine(``"No"``);``      ``i++;``    ``}``  ``}` `  ``// Driver Code``  ``public` `static` `void` `Main(String[] args)``  ``{` `    ``// Fill the complete array with 0``    ``for` `(``int` `i = 0; i < MAX_SIZE; i++)``    ``{``      ``for` `(``int` `j = 0; j < MAX_CHAR; j++)``      ``{``        ``nodecharsCount[i, j] = 0;``      ``}``    ``}``    ``for` `(``int` `i = 0; i < MAX_SIZE; i++)``    ``{``      ``tree[i] = ``new` `List<``int``>();``    ``}` `    ``// Edge between 1 and 2 labelled "bbc"``    ``tree.Add(2);``    ``updateNodecharsCount(``"bbc"``, 2);` `    ``// Edge between 1 and 3 labelled "ac"``    ``tree.Add(3);``    ``updateNodecharsCount(``"ac"``, 3);` `    ``// Update the character count``    ``// from root to the ith node``    ``buildTree(1);` `    ``int``[,] queries = { { 1, 2 }, { 2, 3 }, { 3, 1 }, { 3, 3 } };``    ``int` `q = queries.GetLength(0);` `    ``// Perform the queries``    ``performQueries(queries, q);``  ``}``}`  `// This code is contributed by aashish1995`

## Javascript

 ``
Output:
```Yes
Yes
No
Yes```

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

My Personal Notes arrow_drop_up