AlgoInsight

DSA problem

Maximum Binary Tree

MediumDivide and ConquerPattern: Divide and Conquertop300AmazonMicrosoftGoogleBloombergApple

You are given an integer array nums with no duplicates. A maximum binary tree built from nums is defined recursively: the root is the maximum value in nums. The left subtree is the maximum binary tree built from the prefix of nums to the left of the maximum value. The right subtree is the maximum binary tree built from the suffix to the right of the maximum value. Return the maximum binary tree built from nums.

This recursive definition is itself the divide-and-conquer algorithm. To build the tree for a range [l, r], we divide by finding the index idx of the maximum element in that range, conquer by recursively building the trees for [l, idx-1] and [idx+1, r], and combine by attaching the two sub-trees to a new root whose value is nums[idx]. The base case is an empty range, which yields a null subtree.

Locating the maximum in a range of length k costs O(k). Each level of the recursion processes the entire array exactly once across all of its calls. In the worst case the array is already sorted, producing a skewed tree of height n and an overall time complexity of O(n²). In the average case the tree is well-balanced and the cost drops to O(n log n). A monotonic-stack approach can achieve O(n) but obscures the divide-and-conquer structure; for clarity we present the canonical recursive implementation.

The recursion makes the structural invariant easy to see: every node holds a value greater than every value beneath it, because the recursive call works on a strictly smaller range and selects the maximum of that range as its root. This property is the defining feature of the data structure and falls out naturally from the recursion.

Examples

Example 1
Input: nums = [3,2,1,6,0,5]
Output: [6,3,5,null,2,0,null,null,1]
Explanation: The maximum is 6 at index 3. The left subtree is built from [3,2,1] (root 3 with right child 2 whose right child is 1) and the right subtree from [0,5] (root 5 with left child 0). The output is the level-order serialization of the resulting tree.
Example 2
Input: nums = [3,2,1]
Output: [3,null,2,null,1]
Explanation: The array is strictly decreasing, so each new maximum sits at the start of the remaining range. The tree degenerates into a right-leaning chain 3 -> 2 -> 1.
Example 3
Input: nums = [1,2,3]
Output: [3,2,null,1]
Explanation: The array is strictly increasing, so the maximum is always at the right end of the remaining range. The tree degenerates into a left-leaning chain 3 -> 2 -> 1.

Constraints

3 hints and a full solution walkthrough with step-by-step visualizations are available in the practice editor.

divide-and-conquertreearrayrecursion

Browse all DSA problems