Min Height BST
Problem
Write a function that constructs a Binary Search Tree, BST, out of a given sorted array of distinct integers, and returns the root of the BST
The function should also minimize the height of the BST
i.e. Create a BST that is as balanced as possible
Code
Python
- Solution 1
- Solution 2
- Solution 3
JavaScript
- Solution 1
- Solution 2
- Solution 3
TypeScript
- Solution 1
- Solution 2
- Solution 3
Java
- Solution 1
- Solution 2
- Solution 3
C++
- Solution 1
- Solution 2
- Solution 3
Space-Time Complexity
- Solution 1
- Solution 2
- Solution 3
Time | Space | |
---|---|---|
Worse | O(nlog(n)) | O(n) |
Where n is the length of the array
Inserting a node in a binary tree takes O(log(n)) time and we're going to be doing n operations in log(n) time. Thus, O(nlog(n))
Notes
keep in mind
If we want to have roughly same number of nodes in our left substree as in our right subtree, we need to have the same number of nodes that are strictly smaller than our top node as the number of nodes that are greater than or equal to our top node
The fact that our array is in sorted order is really useful, because we know that the value in the middle of our array has roughly the same amount of smaller values as greater values
If the values in our integer array were not distinct, duplicate values, then we could not guarantee that for the middle value in our array all the values to the left would go in the left subtree, and all the values in the right would go in the right subtree
solution 1
Find the middle element in our sorted array, and make that value the root node in our BST. Then, all the values to the left of the middle element will be placed in the left subtree of the root node in our BST, and all the values to the right of the middle element will be placed in the right subtree
Next, pick the middle element in the left subarray and make that be the root node of the left subtree in our overall BST, and keep applying the logic on all subarrays for its left subtree and its right subtree. We'll be using recursion in our code
If the subarray is even, pick the leftmost number of both middle numbers
Basically, create a recursive function, constructMinHeightBst
, that takes in the array
that we're grabbing values from, the bst
that we're constructing, the starting indices, startIdx
, and ending indices, endIdx
, of the subarray or full array that we're currently looking at. We're going to be calling this recursive function in our main function
In our recursive function, we first handle the base case when we run out of values in a particular subtree, when the starting index gets greater than the ending index, startIdx > endIdx
. So, if the startIdx < endIdx
then we've got multiple values that we can keep adding to the bst
. If startIdx == endIdx
then we've got one value left in that part of the bst
. And, if startIdx > endIdx
then we've reached our base case and we want to break out
Next, grab the middle index between the startIdx
and endIdx
bounds. To calculate the middle index, we're just going to add up the startIdx
and endIdx
and divide them by 2, (startIdx + endIdx) // 2
.
Then, we grab the value that we want to add to our bst
, valueToAdd = array[midIdx]
.
Then, handle the case where our bst
is None/Null and create our root node with our value to add, if bst is None: bst = BST(valueToAdd)
. Or, if we already have a bst
instance, then simply call the insert()
method in our that instance, else: bst.insert(valueToAdd)
Once we're done inserting a node, then we call our recursive function on the two remaining subarrays on either side of our middle index.
Finally, return our bst
, which is going to be our root node
solution 2
Pass down the current root node of a given subtree in our BST, and manually insert the new node that we're creating without calling the .insert()
method. This will allow us to have an algorithm that runs in O(n) time, because inserting any node with this approach is going to be a constant time operation
Basically, keep the same logic from the first solution and after we get the middle index, manually create a new bst node at every call to the recursive function, newBstNode = BST(array[midIdx])
Then, make the same check if bst is None
, otherwise set the left or the right value of the bst
node to be this newBstNode
.
solution 3
This solution will be the cleaner version of solution 2
Here, we are not going to be passing in the bst
in our recursive function. We're going to use the return value of the constructMinHeightBst
function to construct the entire bst
. We're also not going to be using the entire if else logic