Skip to main content
impol.dev

Editorial

Solution walkthrough

Review the explanation, then compare the reference implementation.

Video explanation

Solution

Intuition

Compare the deepest levels in a node's two child subtrees. If one side is taller, all deepest leaves lie there and its answer can be reused. If both sides are equally tall, the current node is their lowest common ancestor.

Approach

Use postorder recursion returning a depth measure and the ancestor of the deepest leaves. Python returns subtree heights: an empty subtree returns zero, and a real node returns one plus the larger child height. Its passed depth argument is not used in this result. JavaScript instead returns the absolute depth argument at an empty subtree and propagates the larger returned depth unchanged; for a nonempty subtree, this is one beyond its deepest leaf's depth. Since the two child roots are at the same depth, these conventions give identical comparisons. Propagate the deeper child's candidate, or choose the current node on a tie. A leaf selects itself. Return the root call's candidate.

# 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 lcaDeepestLeaves(self, root: Optional[TreeNode]) -> Optional[TreeNode]: def dfs(d, node): if not node: return 0, None left_d, left_n = dfs(d + 1, node.left) right_d, right_n = dfs(d + 1, node.right) if left_d > right_d: return left_d + 1, left_n elif right_d > left_d: return right_d + 1, right_n else: return left_d + 1, node return dfs(0, root)[1]

Complexity analysis

For N nodes and tree height H, postorder DFS visits each node once, taking O(N) time and O(H) recursion space. Both displayed implementations are recursive, so an allowed depth near 1000 can exceed the language runtime stack.