Convert Sorted Array to Binary Search Tree - Complete Solution Guide
Convert Sorted Array to Binary Search Tree is LeetCode problem 108, a Easy level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
Given an integer array nums where the elements are sorted in ascending order , convert it to a height-balanced binary search tree . Example 1: Input: nums = [-10,-3,0,5,9] Output: [0,-3,9,-10,null,5] Explanation: [0,-10,5,null,-3,null,9] is also accepted: Example 2: Input: nums = [1,3] Output: [3,1] Explanation: [1,null,3] and [3,1] are both height-balanced BSTs. Constraints: 1 <= nums.length <= 10 4 -10 4 <= nums[i] <= 10 4 nums is sorted in a strictly increasing order.
Detailed Explanation
Our mission here is to transform a simple array of numbers, which is already conveniently sorted in ascending order, into a specific tree structure: a Binary Search Tree (BST) that is also 'height-balanced'. The 'sorted' input is a huge gift, but the 'height-balanced' part is the real constraint. It means that for every single node in our new tree, the heights of its left and right subtrees can differ by at most one. This prevents the tree from degenerating into a linked list and ensures efficient search operations. Consider the example `nums = [-10,-3,0,5,9]`. If we just picked `-10` as the root and built the tree, it would be heavily skewed right, making it effectively a linked list and far from height-balanced. The sorted nature of the array guides us: in a BST, all values to the left of a node are smaller, and all to the right are larger. To achieve height-balance, we intuitively want the root to split the remaining elements as evenly as possible. For our example, `0` is the perfect candidate: `[-10,-3]` become the left candidates, and `[5,9]` the right. This symmetry is the secret to building a compact, balanced tree. The problem statement's allowance for multiple valid outputs for simple cases like `[1,3]` (e.g., `[3,1]` or `[1,null,3]`) reinforces that any strategy which consistently produces *a* height-balanced BST, adhering to both BST rules and the height constraint, is perfectly acceptable. This frees us from finding a single canonical output, letting us focus on the structural properties.
Solution Approach
The provided solution masterfully employs recursion, specifically a divide-and-conquer strategy, to construct the height-balanced BST. The central idea revolves around the fact that for a sorted array, the *middle element* is the optimal choice for the root of a (sub)tree. Why? Because it naturally partitions the remaining elements into two groups of roughly equal size: those smaller than it (for the left subtree) and those larger than it (for the right subtree). The algorithm kicks off with a base case: if the input array `nums` is empty, there's no node to create, so it returns `None`. Otherwise, it finds the middle index (`len(nums) // 2`), creates a `TreeNode` with the value at that `mid` index, and designates it as the current root. The magic then happens with two recursive calls: `root.left` is built by calling `sortedArrayToBST` on the left half of the array (`nums[:mid]`), and `root.right` is built from the right half (`nums[mid+1:]`). By consistently choosing the middle element as the root at every level of recursion, the tree naturally grows with its branches having approximately the same number of nodes. This consistent 'even split' is precisely what guarantees the resulting tree will be height-balanced.
Step-by-Step Algorithm
- Step 1: Check for the base case: If the input array `nums` is empty, return `null` (or `nullptr` in C++).
- Step 2: Find the middle index `mid` of the array.
- Step 3: Create a new `TreeNode` with the value at `nums[mid]` as the root.
- Step 4: Recursively call the function on the left subarray (`nums[:mid]` in Python, `nums[left, mid - 1]` in Java/C++/C) to construct the left subtree and assign it to `root.left`.
- Step 5: Recursively call the function on the right subarray (`nums[mid+1:]` in Python, `nums[mid + 1, right]` in Java/C++/C) to construct the right subtree and assign it to `root.right`.
- Step 6: Return the `root` node.
Key Insights
- **Midpoint as the Balancing Pivot**: The fundamental insight is that selecting the middle element of a *sorted* array to be the root node naturally leads to a height-balanced BST. This choice evenly distributes the remaining elements to the left and right subtrees, minimizing the height difference and preventing skew.
- **Recursive Divide and Conquer**: The problem structure perfectly aligns with a recursive approach. Building the complete BST can be elegantly broken down into creating a root, then recursively solving the identical smaller problem for the left sub-array (to build the left child), and similarly for the right sub-array (for the right child). This pattern ensures that each part of the tree adheres to the balance property.
- **Leveraging the Sorted Property Directly**: The fact that the input array `nums` is already sorted is not just a hint, but the core enabler for this efficient solution. It means we don't need to perform any sorting or complex partitioning to satisfy the BST property; simply picking the middle element provides a ready-made separation into 'lesser' and 'greater' values suitable for left and right children.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(log n)
Topics
This problem involves: Array, Divide and Conquer, Tree, Binary Search Tree, Binary Tree.
Companies
Asked at: Adobe, Airbnb, Apple, Meta, Samsung.