We need to find the lexicographically smallest string that starts at a leaf and ends at the root. Since strings are built from leaf to root, we traverse the tree while building the string by prepending each node's character. When we reach a leaf, we have a complete string to compare. By exploring all paths and keeping track of the minimum string found, we get our answer.
dfs from the root, passing the current string built so far.dfs on that child.# 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 smallestFromLeaf(self, root: Optional[TreeNode]) -> str:
def dfs(root, cur):
if not root:
return
cur = chr(ord('a') + root.val) + cur
if root.left and root.right:
return min(
dfs(root.left, cur),
dfs(root.right, cur)
)
if root.right:
return dfs(root.right, cur)
if root.left:
return dfs(root.left, cur)
return cur
return dfs(root, "")Instead of recursion, we can use a queue to traverse the tree level by level. Each queue entry stores a node along with the string built from the root down to that node. When we encounter a leaf, we compare its complete string with the current minimum. BFS naturally explores all paths, and we simply track the smallest leaf-to-root string found.
# 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 smallestFromLeaf(self, root: Optional[TreeNode]) -> str:
q = deque([(root, "")])
res = None
while q:
node, cur = q.popleft()
cur = chr(ord('a') + node.val) + cur
if not node.left and not node.right:
res = min(res, cur) if res else cur
if node.left:
q.append((node.left, cur))
if node.right:
q.append((node.right, cur))
return resThis approach mirrors the recursive DFS but uses an explicit stack instead of the call stack. We push nodes along with their accumulated strings onto the stack. By processing nodes in LIFO order, we achieve depth-first traversal. The logic for building strings and comparing at leaves remains the same as the recursive version.
# 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 smallestFromLeaf(self, root: Optional[TreeNode]) -> str:
stack = [(root, "")]
res = None
while stack:
node, cur = stack.pop()
cur = chr(ord('a') + node.val) + cur
if not node.left and not node.right:
res = min(res, cur) if res else cur
if node.right:
stack.append((node.right, cur))
if node.left:
stack.append((node.left, cur))
return res