Grokking 75: Top Coding Interview Questions
Ask Author
Back to course home

0% completed

Vote For New Content
Solution: Pseudo-Palindromic Paths in a Binary Tree
Table of Contents

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible

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, 10<sup>5</sup>].
  • 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

  1. Initialize a Function:

    • Define a function pseudoPalindromicPaths which takes the root of the binary tree as input.
  2. Depth-First Search (DFS) Helper Function:

    • Inside pseudoPalindromicPaths, define a helper function dfs which will perform the depth-first search. This function takes a node and a path (represented as an integer) as input.
  3. Base Case for DFS:

    • In the dfs function, check if the node is null. If it is, return 0.
  4. Update Path:

    • Toggle the bit corresponding to the current node's value in the path using the XOR operation (path ^= 1 << node.val).
  5. 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, return 1, otherwise return 0.
  6. Recursive DFS Calls:

    • If the current node is not a leaf, recursively call dfs for the left and right children of the node, passing the updated path as the argument.
  7. Combine Results:

    • Sum the results of the left and right recursive calls and return the total count.
  8. Return Final Result:

    • In the pseudoPalindromicPaths function, call the dfs function with the root node and an initial path of 0. Return the result.

Algorithm Walkthrough

Let's walk through the algorithm step-by-step using the provided binary tree:

    5
   / \
  4   1
 / \   \
4   1   1
  1. Call pseudoPalindromicPaths with root:

    • pseudoPalindromicPaths(root) is called with the root node (value 5).
  2. Initialize DFS with root node and path = 0:

    • dfs(root, 0) is called with root node (value 5) and path = 0.
  3. DFS at node 5:

    • Update path: path ^= 1 << 5 → path = 00000000 ^ 00010000 = 00010000.
    • Node 5 is not a leaf. Proceed with recursive calls.
  4. 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.
  5. 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.
  6. 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.
  7. Combine results at node 4:

    • Results from left and right children: 1 + 0 = 1.
    • Return 1.
  8. 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.
  9. 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.
  10. Combine results at node 1 (right child of 5):

    • Results from left and right children: 0 + 1 = 1.
    • Return 1.
  11. Combine results at root node 5:

    • Results from left and right children: 1 + 1 = 2.
    • Return 2.

Code

Python3
Python3

. . . .

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 O(N), 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 O(N) for a skewed tree. However, for a balanced tree, it is O(log N).

.....

.....

.....

Like the course? Get enrolled and start learning!

Table of Contents

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible