# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def pseudoPalindromicPaths (self, root: TreeNode) -> int:
def dfs(node, path):
if not node:
return 0
path ^= 1 << node.val
if not node.left and not node.right:
return int(path & (path - 1) == 0)
return dfs(node.left, path) + dfs(node.right, path)
return dfs(root, 0)
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
int pseudoPalindromicPaths (TreeNode* root) {
return dfs(root, 0);
}
int dfs(TreeNode* node, int path) {
if (!node) return 0;
path ^= (1 << node->val);
if (!node->left && !node->right) {
return (path & (path - 1)) == 0;
}
return dfs(node->left, path) + dfs(node->right, path);
}
};
// Definition for a binary tree node.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
public int pseudoPalindromicPaths (TreeNode root) {
return dfs(root, 0);
}
private int dfs(TreeNode node, int path) {
if (node == null) return 0;
path ^= (1 << node.val);
if (node.left == null && node.right == null) {
return (path & (path - 1)) == 0 ? 1 : 0;
}
return dfs(node.left, path) + dfs(node.right, path);
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
var pseudoPalindromicPaths = function(root) {
function dfs(node, path) {
if (!node) return 0;
path ^= (1 << node.val);
if (!node.left && !node.right) {
return (path & (path - 1)) === 0 ? 1 : 0;
}
return dfs(node.left, path) + dfs(node.right, path);
}
return dfs(root, 0);
};
Given a binary tree where each node contains a digit from 1
to 9
, you are to count the number of root-to-leaf paths where the sequence of node values along the path can be rearranged to form a palindrome. Such a path is called a pseudo-palindromic path.
Constraints:
1
and 10^5
nodes.1
to 9
.The problem asks us to find paths from the root to every leaf where the node values could be rearranged to form a palindrome. The key insight is that for a sequence to be rearranged as a palindrome, all digits must appear an even number of times, except possibly one digit (which can appear an odd number of times in the center of the palindrome).
A brute-force approach would be to enumerate every root-to-leaf path, count the frequency of each digit along the path, and check if at most one digit has an odd count. However, this approach would be inefficient, especially for large trees.
To optimize, we can use bit manipulation to efficiently keep track of the parity (even or odd) of the counts of digits along the current path. Instead of storing the full count, we just need to know whether the count is odd or even. This can be efficiently represented using a single integer as a bitmask.
We will use depth-first search (DFS) to traverse the binary tree. At each node, we update a bitmask representing the parity of the count of each digit along the current path. Here's how the solution works step-by-step:
path
where the i-th bit is set if the digit i
has been seen an odd number of times along the current path. Since digits are from 1 to 9, we only need 9 bits.
path
using XOR.
path
represents a pseudo-palindromic sequence. This is true if at most one bit is set in path
(i.e., path & (path - 1) == 0
).
This approach is efficient because bitwise operations are fast, and we do not need to store the entire path or count arrays for each recursion.
Consider the following binary tree:
2 / \ 3 1 / \ \ 3 1 1
All root-to-leaf paths:
Let's check each path:
The bitmask at each leaf would look like this:
Brute-force Approach:
The optimized approach is much more efficient, especially for large trees, as it avoids storing full paths or counts and leverages fast bitwise operations.
The key insight for this problem is recognizing that the palindrome property can be efficiently checked using bit manipulation, by tracking the parity of digit counts along each root-to-leaf path. Using DFS with a bitmask, we can traverse the tree in linear time and space, checking the pseudo-palindromic property at each leaf in constant time. This approach is both elegant and practical for large binary trees.