Convert Sorted Array to Balanced BST in DSA Javascript - Time & Space Complexity
We want to know how the time needed to build a balanced binary search tree changes as the input array grows.
How does the number of steps grow when the array size increases?
Analyze the time complexity of the following code snippet.
function sortedArrayToBST(nums) {
if (nums.length === 0) return null;
const mid = Math.floor(nums.length / 2);
const root = { val: nums[mid], left: null, right: null };
root.left = sortedArrayToBST(nums.slice(0, mid));
root.right = sortedArrayToBST(nums.slice(mid + 1, nums.length));
return root;
}
This code builds a balanced binary search tree by picking the middle element as root and recursively doing the same for left and right parts.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls that split the array and create tree nodes.
- How many times: Each element is processed once as the middle element in some recursive call.
- Additional cost: Array slicing creates new arrays at each step, which takes time proportional to the slice size.
Each recursive call splits the array roughly in half, but slicing copies parts of the array, adding extra work.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 50 (due to slicing and recursion) |
| 100 | About 1000 |
| 1000 | About 20000 |
Pattern observation: The work grows faster than just n because slicing copies arrays repeatedly, causing extra cost.
Time Complexity: O(n log n)
This means the time grows a bit faster than the input size because of splitting and copying arrays at each step.
[X] Wrong: "The time complexity is O(n) because each element is visited once."
[OK] Correct: Although each element is chosen once, slicing arrays copies parts repeatedly, adding extra work that makes it slower than O(n).
Understanding this helps you explain how recursion and data copying affect performance, a key skill in building efficient tree structures.
"What if we passed start and end indexes instead of slicing arrays? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem goal
The goal is to build a BST that is balanced, meaning the tree height is minimized for faster search operations.Step 2: Recognize the importance of balance
A balanced BST ensures operations like search, insert, and delete run efficiently, typically in O(log n) time.Final Answer:
To create a BST with minimal height for efficient search -> Option CQuick Check:
Balanced BST = minimal height = efficient search [OK]
- Thinking the goal is to reverse or sort the array again
- Confusing BST with linked list
- Ignoring the balance aspect of the tree
arr in JavaScript for building a balanced BST?Solution
Step 1: Understand array indexing
Array indices start at 0, so to get the middle index, we divide length by 2 and take the floor to get an integer index.Step 2: Use Math.floor for integer index
Using Math.floor(arr.length / 2) gives the correct middle index for both even and odd lengths.Final Answer:
const mid = Math.floor(arr.length / 2); -> Option AQuick Check:
Middle index = floor(length/2) [OK]
- Using division without floor, resulting in float index
- Using Math.ceil which may pick wrong middle
- Using last index instead of middle
[1, 3, 5, 7, 9]?Solution
Step 1: Find the middle element of the array
The array length is 5, middle index = floor(5/2) = 2, so middle element is arr[2] = 5.Step 2: Middle element becomes root
In balanced BST from sorted array, the middle element is chosen as root to keep tree balanced.Final Answer:
5 -> Option BQuick Check:
Middle element = root = 5 [OK]
- Picking first or last element as root
- Using ceil instead of floor for middle index
- Confusing array index with value
function sortedArrayToBST(arr) {
if (!arr.length) return null;
const mid = Math.floor(arr.length / 2);
const root = { val: arr[mid], left: null, right: null };
root.left = sortedArrayToBST(arr.slice(0, mid));
root.right = sortedArrayToBST(arr.slice(mid));
return root;
}
What is the bug in this code?Solution
Step 1: Analyze the slicing for right subtree
The right subtree should exclude the middle element already used as root, so slice should start from mid + 1.Step 2: Identify the bug
Using arr.slice(mid) includes the middle element again in the right subtree, causing duplicate nodes and incorrect tree.Final Answer:
The right subtree slice should start from mid + 1, not mid -> Option AQuick Check:
Right subtree slice = arr.slice(mid + 1) [OK]
- Including middle element in both subtrees
- Wrong base case condition
- Incorrect mid calculation
[-10, -3, 0, 5, 9], what is the preorder traversal (root-left-right) of the balanced BST created by the standard algorithm?Solution
Step 1: Build the balanced BST
Middle index = Math.floor(5/2) = 2, root = 0. Left subarray [-10, -3], length=2, mid=Math.floor(2/2)=1, left child = -3 (left of -3: [-10] mid=0 value -10; right of -3: empty). Right subarray [5, 9], length=2, mid=1, right child = 9 (left of 9: [5]; right of 9: empty).Step 2: Perform preorder traversal (root-left-right)
0, then left subtree: -3 then -10, then right subtree: 9 then 5. Result: [0, -3, -10, 9, 5].Final Answer:
[0, -3, -10, 9, 5] -> Option DQuick Check:
Preorder = root-left-right = [0, -3, -10, 9, 5] [OK]
- Wrong middle element selection for subtrees
- Confusing preorder with inorder or postorder
- Incorrect subtree construction
Ready to prove it?
Pass the test and this pattern moves unknown
