Katkat

Search a Pattern Across the Leaf Text of a Binary Tree

GoogleSoftware Engineer · Onsite

Last updated

Tests binary tree traversal combined with streaming pattern matching (such as the Knuth-Morris-Pratt algorithm) to detect substrings across leaf boundaries without buffering the entire text in memory.

Problem Statement

You are given the root of a binary tree where each leaf node contains a non-empty string val. Internal nodes do not contain text (their val is empty or None).

If you collect the strings from all leaf nodes in a left-to-right order and concatenate them into a single string T, determine whether a given non-empty pattern appears as a contiguous substring in T. The match may start in one leaf and end in another.

To ensure scalability for very large trees where T cannot fit into memory all at once, your solution should process the leaves as a stream with O(|pattern| + height) auxiliary space.

Function Interface

class TreeNode:
    def __init__(self, val="", left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def search_leaf_pattern(root: Optional[TreeNode], pattern: str) -> bool:
    pass

Input & Output

  • Input:
    • root: The root node of a binary tree.
    • pattern: A non-empty string to search for.
  • Output: True if pattern is a contiguous substring of the concatenated leaf text, otherwise False.

Examples

Example 1

         ( )
        /   \
     ( )     ("xyz")
    /   \
("ab")  ("cd")
  • Concatenated leaf text T = "abcdxyz"
  • pattern = "bcdx"
  • Output: True (the pattern spans across leaves "cd" and "xyz").

Example 2

     ( )
    /   \
("hello") ("world")
  • Concatenated leaf text T = "helloworld"
  • pattern = "word"
  • Output: False

Constraints

  • The number of nodes in the tree is between 1 and 10^5.
  • Total characters across all leaves can be up to 10^7.
  • 1 <= len(pattern) <= 10^5.
  • All characters in leaf strings and pattern consist of lowercase English letters.
  • Auxiliary space complexity should be O(|pattern| + H), where H is the height of the tree.

Hints

Hint 1

A standard depth-first search (pre-order or in-order) visits leaves strictly in left-to-right order.

Hint 2

Concatenating all leaf values into one giant string may violate memory limits; consider treating the leaf characters as an incoming stream.

Hint 3

Precompute the prefix function (failure table) of `pattern` using the Knuth-Morris-Pratt (KMP) algorithm, and maintain the current match state across leaf transitions.

Follow-up questions

  • How would you modify your solution to return the starting index (0-based) and the specific leaf node where the match begins?
  • How would you adapt the approach if you need to search for a dictionary of multiple patterns simultaneously in a single pass?
  • If leaves can be mutated dynamically, what data structures would allow efficient pattern search without re-traversing the whole tree?