Problem Statement
Given a sorted array of integers, the task is to construct a balanced Binary Search Tree (BST) from the array elements.
Examples:
Let's consider some examples to understand the problem better.
Example 1:
Input: [-10, -3, 0, 5, 9]
Output:
0
/ \
-3 9
/ /
-10 5
Example 2:
Input: [1, 3, 5, 7, 9, 11]
Output:
5
/ \
1 9
\ / \
3 7 11
Theory:
Before diving into the approaches to solve the problem, let's understand some key concepts:
Binary Search Tree:
A binary tree in which each node has at most two children, and for each node, all elements in the left subtree are less than the node's value, and all elements in the right subtree are greater than the node's value.
Balanced BST:
A BST is balanced if the height of the left and right subtrees of every node differs by at most one. A balanced BST ensures efficient search, insert, and delete operations with a time complexity of O(log n)
, where n is the number of nodes.
Different Approaches
1 Recursive Approach:
Intuition:
The recursive approach leverages the concept of binary search. Since the given array is sorted, selecting the middle element ensures that the resulting BST is balanced. Each time we select the middle element as the root, the left half of the array contributes to the left subtree, and the right half contributes to the right subtree. This process is recursively applied to construct the entire BST.
Algorithm:
constructBST(nums, left, right):
if left > right:
return nullptr
mid = left + (right - left) / 2
root = new TreeNode(nums[mid])
root->left = constructBST(nums, left, mid - 1)
root->right = constructBST(nums, mid + 1, right)
return root
Code Implementation
1 Recursive Approach:
#include <iostream>
#include <vector>
using namespace std;
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
class Solution {
public:
// Function to convert sorted array to BST
TreeNode* sortedArrayToBST(vector<int>& nums) {
// Call the recursive function to construct the BST
return constructBST(nums, 0, nums.size() - 1);
}
// Recursive function to construct BST
TreeNode* constructBST(vector<int>& nums, int left, int right) {
// Base case: If left index is greater than right index, return nullptr
if (left > right) return nullptr;
// Calculate the middle index
int mid = left + (right - left) / 2;
// Create a new TreeNode with the value at the middle index
TreeNode* root = new TreeNode(nums[mid]);
// Recursively construct left subtree from left to mid - 1
root->left = constructBST(nums, left, mid - 1);
// Recursively construct right subtree from mid + 1 to right
root->right = constructBST(nums, mid + 1, right);
// Return the root of the constructed subtree
return root;
}
};
// Helper function to perform inorder traversal of BST
void inorderTraversal(TreeNode* root) {
if (root == nullptr) return;
// Traverse left subtree
inorderTraversal(root->left);
// Print the value of the current node
cout << root->val << " ";
// Traverse right subtree
inorderTraversal(root->right);
}
int main() {
Solution solution;
vector<int> nums = {-10, -3, 0, 5, 9};
// Convert sorted array to BST
TreeNode* root = solution.sortedArrayToBST(nums);
cout << "Inorder Traversal of the constructed BST:" << endl;
// Print inorder traversal of the constructed BST
inorderTraversal(root);
return 0;
}
Explanation:
- We define a
TreeNode
struct to represent the nodes of the binary tree. - The
Solution
class contains thesortedArrayToBST
function, which is the entry point for converting the sorted array to a Binary Search Tree (BST). - Inside the
sortedArrayToBST
function, we call theconstructBST
function, passing the sorted arraynums
along with the indicesleft
andright
. - The
constructBST
function is a recursive function that constructs the BST using the divide-and-conquer approach. - In each recursive call, we calculate the middle index (
mid
) of the current range (left
toright
), and create a newTreeNode
with the value at indexmid
. - We then recursively call
constructBST
for the left half of the array (fromleft
tomid - 1
) and assign the returnedTreeNode
as the left child of the current node. - Similarly, we recursively call
constructBST
for the right half of the array (frommid + 1
toright
) and assign the returnedTreeNode
as the right child of the current node. - The recursion stops when the base case is reached, i.e., when
left
is greater thanright
, in which case we returnnullptr
. - Finally, we print the inorder traversal of the constructed BST to verify its correctness.
Complexity Analysis
1 Recursive Approach:
Time Complexity: O(n)
- The time complexity of this approach is
O(n)
, wheren
is the number of elements in the input sorted array. - Each element in the array is visited exactly once, and for each element, a constant amount of work is done.
- Hence, the overall time complexity is linear,
O(n)
.
Space Complexity: O(n)
- The space complexity of this approach is also
O(n)
. - This is because the recursive calls consume space on the call stack, and in the worst case, the maximum depth of the recursion is
n
(if the tree is completely unbalanced). - Therefore, the overall space complexity is linear,
O(n)