We're given a sorted array and need to build a binary search tree (BST) from it that's also height-balanced. The BST property means every node's left subtree contains only smaller values and the right subtree contains only larger values. Height-balanced means that at every node, the left and right subtree heights differ by at most 1.
A sorted array is the in-order traversal of the BST we want to build. To make the tree height-balanced, we want roughly equal numbers of nodes on the left and right of each subtree. That points to picking the middle element as the root, then recursing on the left half for the left subtree and the right half for the right subtree. This is a divide and conquer pattern.
1 <= nums.length <= 10^4 → With n up to 10,000, we can build the tree in O(n). Each element becomes exactly one node, so O(n) is optimal.-10^4 <= nums[i] <= 10^4 → Node values are small integers. No overflow concerns.nums is sorted in strictly increasing order → No duplicates. Everything left of any chosen root is strictly smaller and everything right of it is strictly larger, so the BST property needs no tie handling.A sorted array is the in-order traversal of a BST, and to make the BST height-balanced, each subtree needs roughly the same number of nodes on the left and right. The middle element achieves that.
If we pick the middle element as the root, all elements before it (the left half) form the left subtree, and all elements after it (the right half) form the right subtree. Both halves differ in size by at most 1. For each half, we apply the same logic: pick its middle element as the root of that subtree, and recurse.
This is divide and conquer: split the array at the middle, build each half recursively, and combine by making the middle element the parent of the two subtree roots.
Two invariants hold at every recursive call. BST property: the array is sorted, so every element in nums[left..mid-1] is smaller than nums[mid] and every element in nums[mid+1..right] is larger. Each node's left subtree contains only smaller values and its right subtree only larger ones.
Balance: the two halves differ in size by at most 1, and this holds at every level of recursion, so the subtree heights at any node differ by at most 1. The resulting tree's height is ceil(log2(n+1)), the minimum possible. The tree is height-balanced by construction.
Trace nums = [-10, -3, 0, 5, 9]. The array view shows the range each recursive call covers and the middle index it picks; the tree view below it shows the node each call creates.
O(n) time is optimal because the output tree has n nodes. The remaining variation builds the same tree without recursion.
The same construction works without recursion. An explicit stack replaces the call stack: instead of relying on the runtime to track which subarray ranges still need processing, we manage a stack of "tasks" ourselves.
Each task on the stack stores: the parent node, which child (left or right) this task should attach to, and the subarray bounds (left, right). We process tasks the same way the recursive version does: find the middle, create a node, attach it to the parent, then push two new tasks for the left and right halves. Pushing the right half's task before the left half's means the left task sits on top of the stack and is popped first, so nodes are created in the same order as the recursive version.
The same input traced through the stack version. Each step shows the task popped from the stack, the range it covers, and the node it creates; tasks with an empty range are popped and skipped. The nodes appear in the same order as in the recursive version because the left task is always pushed last.