File: closest-binary-search-tree-value/solution.py

Date: 2026-06-06

Time: 15:47

Purpose

This file implements LeetCode problem 270 — Closest Binary Search Tree Value. Given a BST and a float target, it finds the node value closest to the target, breaking ties by returning the smaller value. The file is self-contained: it defines the tree data structure, the solution, a tree builder helper, and a full test suite.

Key Components

TreeNode

Standard BST node with val, left, right. Uses the union-style type hint ("TreeNode | None") for children alongside Optional[TreeNode] on the solution method — a minor inconsistency but functionally equivalent.

Solution.closestValue(root, target) -> int

The core algorithm. Walks the BST iteratively, maintaining the best candidate in closest. At each node it:

1. Updates closest if the current node is strictly nearer, or equally near but numerically smaller (the tie-break rule).

2. Chooses a direction — goes left if target < node.val, right otherwise — pruning the half of the tree that can't contain a closer value.

This is O(h) time, O(1) space, where h is the tree height.

_build(vals) -> Optional[TreeNode]

Module-level helper that constructs a BST from a level-order list (BFS encoding), where None entries represent absent children. Used exclusively by the test suite.

TestClosestValue

Eight test cases covering: the LeetCode examples, exact match, tie-breaking (equidistant values), left-only and right-only skewed trees, and extreme targets (far positive/negative).

Patterns

Dependencies

Imports: typing.Optional (type hint), unittest (test framework). No project-internal dependencies.

Imported by: The test_solution.py in this same directory. The massive "Imported By" list in the prompt is misleading — those are unrelated test files across the repo that happen to share the same module name pattern; they don't actually import *this* file.

Flow


closestValue(root=4, target=3.71)
  closest = 4
  node = 4  →  |4 - 3.71| = 0.29, closest stays 4
                target < 4 → go left
  node = 2  →  |2 - 3.71| = 1.71 > 0.29, closest stays 4
                target > 2 → go right
  node = 3  →  |3 - 3.71| = 0.71 > 0.29, closest stays 4
                target > 3 → go right
  node = None → return 4

The key insight: the BST property guarantees that once you choose a direction, all values in the discarded subtree are farther from the target than the current node — so you never miss the optimal answer.

Invariants

Error Handling

None. The code assumes valid input (non-null root, valid BST). There's no defensive checking — which is standard for LeetCode solutions where constraints guarantee valid input.

The _build helper also has a subtle issue: if vals has an odd number of elements after the root, the inner loop's second if i < len(vals) check prevents an out-of-bounds access, but it does mean trailing None values are silently ignored.

Topics to Explore

Beliefs