medium Pseudo-Palindromic Paths in a Binary Tree
Problem Statement
Given a binary tree where each node has a value between 1 and 9, return the number of "pseudo-palindromic" paths from the root node to any leaf node.
A path is called "pseudo-palindromic" if the values along the path can be rearranged to form a palindrome.
Examples
Example 1
- Input:
5 / \ 4 1 / \ \ 4 1 1 - Expected Output: 2
- Justification: The paths are:
- 5 → 4 → 4 (pseudo-palindromic: "5, 4, 4" can be rearranged to "4, 5, 4")
- 5 → 1 → 1 (pseudo-palindromic: "5, 1, 1" can be rearranged to "1, 5, 1")
Example 2
- Input:
2 / \ 3 1 / / \ 3 1 1 - Expected Output: 3
- Justification: All 3 paths are pseudo-palindromic paths.
Example 3
- Input:
9 / \ 5 5 / / \ 5 1 7 - Expected Output: 1
- Justification: The only path 9 → 5 → 5 is a psuedo-palindromic path.
Constraints:
- The number of nodes in the tree is in the range [1, 105].
- 1 <= Node.val <= 9
Try it yourself
Try solving this question here:
✅ Solution Pseudo-Palindromic Paths in a Binary Tree
Problem Statement
Given a binary tree where each node has a value between 1 and 9, return the number of "pseudo-palindromic" paths from the root node to any leaf node.
A path is called "pseudo-palindromic" if the values along the path can be rearranged to form a palindrome.
Examples
Example 1
- Input:
5 / \ 4 1 / \ \ 4 1 1 - Expected Output: 2
- Justification: The paths are:
- 5 → 4 → 4 (pseudo-palindromic: "5, 4, 4" can be rearranged to "4, 5, 4")
- 5 → 1 → 1 (pseudo-palindromic: "5, 1, 1" can be rearranged to "1, 5, 1")
Example 2
- Input:
2 / \ 3 1 / / \ 3 1 1 - Expected Output: 3
- Justification: All 3 paths are pseudo-palindromic paths.
Example 3
- Input:
9 / \ 5 5 / / \ 5 1 7 - Expected Output: 1
- Justification: The only path 9 → 5 → 5 is a psuedo-palindromic path.
Constraints:
- The number of nodes in the tree is in the range [1, 105].
- 1 <= Node.val <= 9
Solution
To solve this problem, we will traverse the binary tree using Depth-First Search (DFS). During the traversal, we will keep track of the count of each digit in the current path using an array. For each leaf node, we will check if the path from the root to this node is pseudo-palindromic by verifying if at most one digit has an odd count. This check is based on the property of palindromes, where at most one character can have an odd frequency.
Our approach will be effective because it leverages the tree's structure and efficiently checks for pseudo-palindromic paths using counting and simple arithmetic operations.
Step-by-step Algorithm
-
Initialize a Function:
- Define a function
pseudoPalindromicPathswhich takes the root of the binary tree as input.
- Define a function
-
Depth-First Search (DFS) Helper Function:
- Inside
pseudoPalindromicPaths, define a helper functiondfswhich will perform the depth-first search. This function takes a node and a path (represented as an integer) as input.
- Inside
-
Base Case for DFS:
- In the
dfsfunction, check if the node isnull. If it is, return0.
- In the
-
Update Path:
- Toggle the bit corresponding to the current node's value in the path using the XOR operation (
path ^= 1 << node.val).
- Toggle the bit corresponding to the current node's value in the path using the XOR operation (
-
Check if Leaf Node:
- Check if the current node is a leaf node (i.e., it has no left or right child). If it is a leaf, check if at most one bit is set in the path (which means the path can form a palindrome). This can be checked using
(path & (path - 1)) == 0. If the condition is true, return1, otherwise return0.
- Check if the current node is a leaf node (i.e., it has no left or right child). If it is a leaf, check if at most one bit is set in the path (which means the path can form a palindrome). This can be checked using
-
Recursive DFS Calls:
- If the current node is not a leaf, recursively call
dfsfor the left and right children of the node, passing the updated path as the argument.
- If the current node is not a leaf, recursively call
-
Combine Results:
- Sum the results of the left and right recursive calls and return the total count.
-
Return Final Result:
- In the
pseudoPalindromicPathsfunction, call thedfsfunction with the root node and an initial path of0. Return the result.
- In the
Algorithm Walkthrough
Let's walk through the algorithm step-by-step using the provided binary tree:
5
/ \
4 1
/ \ \
4 1 1
-
Call pseudoPalindromicPaths with root:
pseudoPalindromicPaths(root)is called with the root node (value 5).
-
Initialize DFS with root node and path = 0:
dfs(root, 0)is called with root node (value 5) and path = 0.
-
DFS at node 5:
- Update path:
path ^= 1 << 5→ path = 00000000 ^ 00010000 = 00010000. - Node 5 is not a leaf. Proceed with recursive calls.
- Update path:
-
DFS at node 4 (left child of 5):
- Update path:
path ^= 1 << 4→ path = 00010000 ^ 00001000 = 00011000. - Node 4 is not a leaf. Proceed with recursive calls.
- Update path:
-
DFS at node 4 (left child of 4):
- Update path:
path ^= 1 << 4→ path = 00011000 ^ 00001000 = 00010000. - Node 4 is a leaf. Check if path can form a palindrome:
(00010000 & (00010000- 1)) == 0→ true. - Return 1.
- Update path:
-
DFS at node 1 (right child of 4):
- Update path:
path ^= 1 << 1→ path = 00011000 ^ 00000010 = 00011010. - Node 1 is a leaf. Check if path can form a palindrome:
(00011010 & (00011010 - 1)) == 0→ false. - Return 0.
- Update path:
-
Combine results at node 4:
- Results from left and right children: 1 + 0 = 1.
- Return 1.
-
DFS at node 1 (right child of 5):
- Update path:
path ^= 1 << 1→ path = 00010000 ^ 00000010 = 00010010. - Node 1 is not a leaf. Proceed with recursive calls.
- Update path:
-
DFS at node 1 (right child of 1):
- Update path:
path ^= 1 << 1→ path = 00010010 ^ 00000010 = 00010000. - Node 1 is a leaf. Check if path can form a palindrome:
(32 & (32 - 1)) == 0→ true. - Return 1.
- Update path:
-
Combine results at node 1 (right child of 5):
- Results from left and right children: 0 + 1 = 1.
- Return 1.
-
Combine results at root node 5:
- Results from left and right children: 1 + 1 = 2.
- Return 2.
Code
import java.util.*;
// class TreeNode {
// int val;
// TreeNode left;
// TreeNode right;
// TreeNode(int x) {
// val = x;
// }
// }
class Solution {
public int pseudoPalindromicPaths(TreeNode root) {
return dfs(root, 0);
}
// Depth-First Search function
private int dfs(TreeNode node, int path) {
if (node == null) return 0; // If the node is null, return 0
path ^= 1 << node.val; // Toggle the bit corresponding to the current node value
if (node.left == null && node.right == null) { // Check if the node is a leaf
// Check if at most one bit is set in 'path'
return (path & (path - 1)) == 0 ? 1 : 0;
}
// Recursive calls for left and right children
return dfs(node.left, path) + dfs(node.right, path);
}
public static void main(String[] args) {
Solution sol = new Solution();
// Example 1
TreeNode root1 = new TreeNode(5);
root1.left = new TreeNode(4);
root1.right = new TreeNode(1);
root1.left.left = new TreeNode(4);
root1.left.right = new TreeNode(1);
root1.right.right = new TreeNode(1);
System.out.println(sol.pseudoPalindromicPaths(root1)); // Output: 2
// Example 2
TreeNode root2 = new TreeNode(2);
root2.left = new TreeNode(3);
root2.right = new TreeNode(1);
root2.left.left = new TreeNode(3);
root2.right.left = new TreeNode(1);
root2.right.right = new TreeNode(1);
System.out.println(sol.pseudoPalindromicPaths(root2)); // Output: 3
// Example 3
TreeNode root3 = new TreeNode(9);
root3.left = new TreeNode(5);
root3.right = new TreeNode(5);
root3.left.left = new TreeNode(5);
root3.right.left = new TreeNode(1);
root3.right.right = new TreeNode(7);
System.out.println(sol.pseudoPalindromicPaths(root3)); // Output: 1
}
}
Complexity Analysis
Time Complexity
- The algorithm visits each node exactly once, performing constant-time operations for each node (bit manipulation and checking if it's a leaf). Thus, the time complexity is
, where N is the number of nodes in the binary tree.
Space Complexity
- The space complexity is determined by the depth of the recursion stack, which is proportional to the height of the tree (H). In the worst case, this could be
for a skewed tree. However, for a balanced tree, it is .
🤖 Don't fully get this? Learn it with Claude
Stuck on Pseudo-Palindromic Paths in a Binary Tree? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Pseudo-Palindromic Paths in a Binary Tree** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Pseudo-Palindromic Paths in a Binary Tree** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Pseudo-Palindromic Paths in a Binary Tree**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Pseudo-Palindromic Paths in a Binary Tree**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.