Algorithm

Convert Sorted Array to BST

Trees Pattern

Convert Sorted Array to BST

Given an integer array nums sorted in strictly increasing order, build a height-balanced binary search tree containing exactly those values, and return its root. Binary search tree means every node's value is greater than all values in its left subtree and smaller than all values in its right subtree. Height-balanced means that at every node the two subtree heights differ by at most 1. Several valid trees usually exist; any one of them is accepted.

CONSTRAINTS
  • 1 <= nums.length <= 10⁴
  • -10⁴ <= nums[i] <= 10⁴
  • nums is sorted in strictly increasing order, so there are no duplicates
  • Any height-balanced BST over these values is accepted
EXAMPLE 1
Input: nums = [-10,-3,0,5,9]
Output: [0,-3,9,-10,null,5]
0 is the middle value, so it splits the rest into two equal groups of two, which become the left and right subtrees. The tree [0,-10,5,null,-3,null,9] is equally correct — both are height-balanced and both read back as the original sorted array.
EXAMPLE 2
Input: nums = [1,3]
Output: [3,1]
With an even count there is no exact middle. Taking the upper of the two makes 3 the root with 1 on its left; taking the lower gives [1,null,3]. Both have heights differing by 1 at every node, so both qualify.
EXAMPLE 3
Input: nums = [0]
Output: [0]
One value makes a single node, which is trivially both a search tree and balanced.
EXAMPLE 4
Input: nums = [-10,-3,0,5,9,12,20]
Output: [5,-3,12,-10,0,9,20]
Seven values fill a perfect tree: the middle becomes the root, and each half of three splits the same way. Nothing about the input is special here — repeated halving always produces the flattest tree possible.
Is there more than one correct answer?
Usually yes. Whenever a range has an even number of values, either middle may be chosen, and each choice yields a different but equally valid tree.
What exactly does height-balanced require?
At *every* node, not just the root, the two subtree heights differ by at most 1 — the same condition checked in Balanced Binary Tree.
Can I just insert the values one at a time?
You can, and the result is a BST, but inserting sorted values produces a single right-leaning chain of height N. It satisfies the search property and fails balance completely.
Are duplicates possible?
No, the input is strictly increasing. That is convenient, since duplicates force a policy decision about which side equal values belong on.

Two separate demands are being made here, and it pays to keep them apart. The tree must be a binary search tree, and it must be height-balanced.

A binary search tree is an ordinary binary tree with one extra rule imposed at every node: everything in its left subtree is smaller than it, and everything in its right subtree is larger. That rule is what makes searching cheap — comparing your target against a node tells you which single subtree to enter and lets you discard the other one entirely, without looking inside it. Discarding half the remaining candidates at each step is what turns a search into roughly log₂N comparisons instead of N.

But that speed is a promise about height, not about the ordering rule, and the ordering rule alone does not deliver it. Insert 1, 2, 3, 4, 5 into an empty BST in that order: each value is larger than everything present, so each becomes the right child of the last, and you get a chain of height 5. The search property holds perfectly and searching still costs N steps. Hence the second demand — height-balanced, in the sense checked by Balanced Binary Tree: at every node the two subtree heights differ by at most 1, which keeps the height at O(log N).

What the sorted array already tells you

Here is the connection worth internalising. Read a binary search tree in in-order — left subtree, node, right subtree — and the values come out in increasing order. That is not a coincidence: in-order visits everything smaller than a node before it and everything larger after it, which is precisely the BST rule restated as a sequence.

So the given array is the in-order reading of the tree we must build. The values' relative order is fixed and not ours to choose. All the freedom lies in deciding which value sits at the top of each range — and that choice alone determines the height.

Choosing the root to force balance

Pick some value as the root. Everything before it in the array must go to its left, everything after to its right — the BST rule leaves no alternative. So the split sizes are decided entirely by where in the range you pick.

Pick the first value, and the left subtree gets nothing while the right gets everything: that is the degenerate chain again. Pick the middle, and the two sides differ in size by at most one, which is the most even split available. Apply the same choice recursively to each half and no node can ever end up lopsided — with n values, each side gets ⌊(n-1)/2⌋ or ⌈(n-1)/2⌉ of them, so the two subtree heights can differ by at most 1 at every node, which is exactly the balance condition. Repeated halving also means the height is about log₂N, since the range size halves each level.

python
def build(lo, hi):                  # inclusive index range
    if lo > hi:
        return None                 # empty range: no subtree here
    mid = (lo + hi) // 2            # the middle value becomes this subtree's root
    node = Node(nums[mid])
    node.left  = build(lo, mid - 1) # strictly smaller values
    node.right = build(mid + 1, hi) # strictly larger values
    return node

return build(0, len(nums) - 1)

The node is created before its children, since we need something to attach them to — a pre-order construction, the same shape as the two reconstruction problems, and for the same reason.

Crucial Notethe base case is lo > hi, not lo == hi. A range holding a single value is a real subtree that must still produce a leaf node; a range where the indices have crossed holds nothing and produces null. Testing for equality drops every leaf whose parent picked the boundary, which loses roughly half the array. It is also why mid - 1 and mid + 1 are correct rather than mid: the middle value has been consumed by this node, so neither half may include it, and passing mid again recurses forever on a one-element range.

When the range has an even number of values there is no exact middle, and (lo + hi) // 2 picks the lower one. Choosing the upper instead is equally valid and simply produces a different accepted tree — the balance argument above never depended on which of the two you take.

Worked example:nums = [-10, -3, 0, 5, 9]
- Range [0..4]. mid = 2, value 0, which becomes the root. Left range [0..1], right range [3..4].
- Left, range [0..1]. mid = 0, value -10. Its left range is [0..-1] — crossed, so null. Its right range is [1..1].
- Range [1..1]. mid = 1, value -3, a leaf. So -3 hangs on the right of -10.
- Right, range [3..4]. mid = 3, value 5, with an empty left and right range [4..4].
- Range [4..4]. mid = 4, value 9, a leaf, hanging right of 5.
- The tree: 0 at the top, -10 and 5 beneath it, with -3 and 9 as leaves. Every node's two sides differ in height by at most 1, and reading it in-order gives back -10, -3, 0, 5, 9.
Cost, and the idea to carry

Each value produces exactly one node and is touched once: O(N) time, which is optimal since every value must appear in the output. The recursion is O(log N) deep because the range halves each level, so the extra space is O(log N) — noticeably better than the O(H) of most tree recursions, precisely because we are guaranteeing the tree is shallow rather than accepting whatever shape we are handed.

Two things generalise. First, in-order is the traversal that exposes a BST's ordering, and that fact drives most BST problems: validating one, finding its k-th smallest value, or converting it back to a sorted list are all in-order walks. Second, the balancing move — take the middle so both sides stay equal — is the same instinct behind binary search and merge sort, and it recurs whenever a structure's cost depends on its depth. When someone hands you sorted data and asks for a balanced structure, the middle element is almost always the answer.

Interactive Strategy Visualization

Array to Balanced BST

Binary Split Strategy

Sorted Array Input
-10
-3
0
5
9
0
Explanation
Starting with sorted array. Goal: Pick middle to balance BST.

Strategy

Focus on the recursive nature of trees: solve for subtrees and combine results at the root.

"Divide and Conquer: Subproblem → Recurrence → Result"

O(N log N) Insert Values One By One (Degenerates To O(N²) Chain)
O(N) Time · O(log N) Space Recursive Midpoint Split