Given a sorted array arr[]. Convert it into a Balanced Binary Search Tree (BST). Return the root of the BST.
A Balanced Binary Search Tree (BST) is a type of binary tree in which the difference between the heights of the left and right subtrees of every node is at most one.
[Expected Approach - 1] Using Recursion - O(n) Time and O(n) Space
The idea is to use recursion to build the tree from a sorted array. We first find the middle element of the array and make it the root of the tree. Then we recursively repeat the same process for the left subarray (to form the left subtree) and the right subarray (to form the right subtree).
Why the Middle Element? Choosing the middle element ensures that:
Half of the elements lie on the left side (smaller values)
Half of the elements lie on the right side (larger values)
This keeps the number of nodes in both subtrees as equal as possible, ensuring the tree remains height-balanced.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<queue>#include<algorithm>usingnamespacestd;// Node structureclassNode{public:intdata;Node*left;Node*right;Node(intdata){this->data=data;left=right=nullptr;}};// Function to get HeightintgetHeight(Node*root,inth){if(root==nullptr)returnh-1;returnmax(getHeight(root->left,h+1),getHeight(root->right,h+1));}// Print level ordervoidlevelOrder(Node*root){queue<pair<Node*,int>>q;q.push({root,0});intlastLevel=0;// function to get the height of treeintheight=getHeight(root,0);// printing the level order of treewhile(!q.empty()){autotop=q.front();q.pop();Node*node=top.first;intlvl=top.second;if(lvl>lastLevel){cout<<"";lastLevel=lvl;}// all levels are printedif(lvl>height)break;if(node->data!=-1)cout<<node->data<<" ";// printing null nodeelsecout<<"N ";// null node has no childrenif(node->data==-1)continue;if(node->left==nullptr)q.push({newNode(-1),lvl+1});elseq.push({node->left,lvl+1});if(node->right==nullptr)q.push({newNode(-1),lvl+1});elseq.push({node->right,lvl+1});}}// Recursive Function to Create BST//Driver Code EndsNode*sortedArrayToBSTRecur(vector<int>&arr,intstart,intend){if(start>end)returnnullptr;intmid=start+(end-start)/2;Node*root=newNode(arr[mid]);// Divide from middle elementroot->left=sortedArrayToBSTRecur(arr,start,mid-1);root->right=sortedArrayToBSTRecur(arr,mid+1,end);returnroot;}// Function which return BSTNode*sortedArrayToBST(vector<int>&arr){returnsortedArrayToBSTRecur(arr,0,arr.size()-1);}//Driver Code Startsintmain(){vector<int>arr={1,5,9,14,23,27};Node*root=sortedArrayToBST(arr);levelOrder(root);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;importjava.util.List;importjava.util.Queue;importjava.util.LinkedList;// Node strcutureclassNode{intdata;Nodeleft,right;Node(intdata){this.data=data;this.left=null;this.right=null;}}classGFG{// function to get heightstaticintgetHeight(Noderoot,inth){if(root==null)returnh-1;returnMath.max(getHeight(root.left,h+1),getHeight(root.right,h+1));}// Print level orderstaticvoidlevelOrder(Noderoot){Queue<List<Object>>queue=newLinkedList<>();queue.offer(List.of(root,0));intlastLevel=0;// function to get the height of treeintheight=getHeight(root,0);// printing the level order of treewhile(!queue.isEmpty()){List<Object>top=queue.poll();Nodenode=(Node)top.get(0);intlvl=(int)top.get(1);if(lvl>lastLevel){System.out.println();lastLevel=lvl;}// all levels are printedif(lvl>height)break;// printing null nodeSystem.out.print((node.data==-1?"N":node.data)+" ");// null node has no childrenif(node.data==-1)continue;if(node.left==null)queue.offer(List.of(newNode(-1),lvl+1));elsequeue.offer(List.of(node.left,lvl+1));if(node.right==null)queue.offer(List.of(newNode(-1),lvl+1));elsequeue.offer(List.of(node.right,lvl+1));}}//Driver Code Ends// Recursive Function to Create BSTstaticNodesortedArrayToBSTRecur(int[]arr,intstart,intend){if(start>end)returnnull;intmid=start+(end-start)/2;Noderoot=newNode(arr[mid]);// Divide from middle elementroot.left=sortedArrayToBSTRecur(arr,start,mid-1);root.right=sortedArrayToBSTRecur(arr,mid+1,end);returnroot;}// Function which return BSTstaticNodesortedArrayToBST(int[]arr){returnsortedArrayToBSTRecur(arr,0,arr.length-1);}//Driver Code Startspublicstaticvoidmain(String[]args){int[]arr={1,5,9,14,23,27};Noderoot=sortedArrayToBST(arr);levelOrder(root);}}//Driver Code Ends
Python
#Driver Code Startsfromcollectionsimportdeque# Node structureclassNode:def__init__(self,data):self.data=dataself.left=Noneself.right=None# function to get heightdefgetHeight(root,h):ifrootisNone:returnh-1returnmax(getHeight(root.left,h+1),getHeight(root.right,h+1))# Print level orderdeflevelOrder(root):queue=deque([[root,0]])lastLevel=0# function to get the height of treeheight=getHeight(root,0)# printing the level order of treewhilequeue:node,lvl=queue.popleft()iflvl>lastLevel:print()lastLevel=lvl# all levels are printediflvl>height:break# printing null nodeprint("N"ifnode.data==-1elsenode.data,end=" ")# null node has no childrenifnode.data==-1:continueifnode.leftisNone:queue.append([Node(-1),lvl+1])else:queue.append([node.left,lvl+1])ifnode.rightisNone:queue.append([Node(-1),lvl+1])else:queue.append([node.right,lvl+1])#Driver Code Ends# Recursive Function to Create BSTdefsortedArrayToBSTRecur(arr,start,end):ifstart>end:returnNonemid=start+(end-start)//2root=Node(arr[mid])# Divide from middle elementroot.left=sortedArrayToBSTRecur(arr,start,mid-1)root.right=sortedArrayToBSTRecur(arr,mid+1,end)returnroot# Function which return BSTdefsortedArrayToBST(arr):returnsortedArrayToBSTRecur(arr,0,len(arr)-1)#Driver Code Startsif__name__=="__main__":arr=[1,5,9,14,23,27]root=sortedArrayToBST(arr)levelOrder(root)#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;// Node structureclassNode{publicintdata;publicNodeleft,right;publicNode(intdata){this.data=data;this.left=null;this.right=null;}}classGFG{staticintGetHeight(Noderoot,inth){if(root==null)returnh-1;returnMath.Max(GetHeight(root.left,h+1),GetHeight(root.right,h+1));}staticvoidlevelOrder(Noderoot){Queue<(Node,int)>queue=newQueue<(Node,int)>();queue.Enqueue((root,0));intlastLevel=0;// function to get the height of treeintheight=GetHeight(root,0);// printing the level order of treewhile(queue.Count>0){var(node,lvl)=queue.Dequeue();if(lvl>lastLevel){Console.WriteLine();lastLevel=lvl;}// all levels are printedif(lvl>height)break;// printing null nodeConsole.Write((node.data==-1?"N":node.data.ToString())+" ");// null node has no childrenif(node.data==-1)continue;if(node.left==null)queue.Enqueue((newNode(-1),lvl+1));elsequeue.Enqueue((node.left,lvl+1));if(node.right==null)queue.Enqueue((newNode(-1),lvl+1));elsequeue.Enqueue((node.right,lvl+1));}}//Driver Code Ends// Recursive Function to Create BSTstaticNodesortedArrayToBSTRecur(int[]arr,intstart,intend){if(start>end)returnnull;intmid=start+(end-start)/2;Noderoot=newNode(arr[mid]);// Divide from middle elementroot.left=sortedArrayToBSTRecur(arr,start,mid-1);root.right=sortedArrayToBSTRecur(arr,mid+1,end);returnroot;}// Recursive Function to Create BSTstaticNodesortedArrayToBST(int[]arr){returnsortedArrayToBSTRecur(arr,0,arr.Length-1);}//Driver Code StartsstaticvoidMain(){int[]arr={1,5,9,14,23,27};Noderoot=sortedArrayToBST(arr);levelOrder(root);}}//Driver Code Ends
JavaScript
//Driver Code Starts// Node structureclassNode{constructor(data){this.data=data;this.left=null;this.right=null;}}// Custom Queue ImplementationclassQueue{constructor(){this.items={};this.headIndex=0;this.tailIndex=0;}enqueue(item){this.items[this.tailIndex]=item;this.tailIndex++;}dequeue(){if(this.isEmpty())returnnull;letitem=this.items[this.headIndex];deletethis.items[this.headIndex];this.headIndex++;returnitem;}isEmpty(){returnthis.tailIndex===this.headIndex;}size(){returnthis.tailIndex-this.headIndex;}}functiongetHeight(root,h){if(root===null)returnh-1;returnMath.max(getHeight(root.left,h+1),getHeight(root.right,h+1));}functionlevelOrder(root){letq=newQueue();q.enqueue([root,0]);letlastLevel=0;// function to get the height of treeletheight=getHeight(root,0);// printing the level order of treewhile(!q.isEmpty()){let[node,lvl]=q.dequeue();if(lvl>lastLevel){console.log("");lastLevel=lvl;}// all levels are printedif(lvl>height)break;// printing null nodeprocess.stdout.write((node.data===-1?"N":node.data)+" ");// null node has no childrenif(node.data===-1)continue;if(node.left===null)q.enqueue([newNode(-1),lvl+1]);elseq.enqueue([node.left,lvl+1]);if(node.right===null)q.enqueue([newNode(-1),lvl+1]);elseq.enqueue([node.right,lvl+1]);}}//Driver Code Ends// Recursive Function to Create BSTfunctionsortedArrayToBSTRecur(arr,start,end){if(start>end)returnnull;letmid=start+Math.floor((end-start)/2);letroot=newNode(arr[mid]);// Divide from middle elementroot.left=sortedArrayToBSTRecur(arr,start,mid-1);root.right=sortedArrayToBSTRecur(arr,mid+1,end);returnroot;}// Function which return BSTfunctionsortedArrayToBST(arr){returnsortedArrayToBSTRecur(arr,0,arr.length-1);}// Driver code//Driver Code Startsconstarr=[1,5,9,14,23,27];constroot=sortedArrayToBST(arr);levelOrder(root);//Driver Code Ends
Output
9
1 23
N 5 14 27
[Expected Approach - 2] Using queue - O(n) Time and O(n) Space
The idea is to traverse the tree in level order manner, starting from root node. Check for each node, if left subtree exists, then create the left node and push it into queue. Similarly, if right subtree exists, then create the right node and push it into queue.
Step-by-step approach:
Initialize a queue with the root node (middle of array) and its range [0, n-1].
While the queue isn’t empty: Pop the front node with its [start, end] range. Find mid = (start + end) / 2. If start < mid, create the left child using the middle of [start, mid-1], link it, and push it with its range. If end > mid, create the right child using the middle of [mid+1, end], link it, and push it with its range.
Return the root.
C++
//Driver Code Starts#include<iostream>#include<queue>#include<vector>#include<algorithm>usingnamespacestd;// Node structureclassNode{public:intdata;Node*left;Node*right;Node(intdata){this->data=data;left=right=nullptr;}};intgetHeight(Node*root,inth){if(root==nullptr)returnh-1;returnmax(getHeight(root->left,h+1),getHeight(root->right,h+1));}voidlevelOrder(Node*root){queue<pair<Node*,int>>q;q.push({root,0});intlastLevel=0;// function to get the height of treeintheight=getHeight(root,0);// printing the level order of treewhile(!q.empty()){auto[node,lvl]=q.front();q.pop();if(lvl>lastLevel){cout<<"";lastLevel=lvl;}// all levels are printedif(lvl>height)break;// printing null nodeif(node->data!=-1)cout<<node->data<<" ";elsecout<<"N ";// null node has no childrenif(node->data==-1)continue;if(node->left==nullptr)q.push({newNode(-1),lvl+1});elseq.push({node->left,lvl+1});if(node->right==nullptr)q.push({newNode(-1),lvl+1});elseq.push({node->right,lvl+1});}}//Driver Code Ends// helper class to store {node, start, end}classData{public:Node*node;intstart,end;Data(Node*node,intstart,intend){this->node=node;this->start=start;this->end=end;}};Node*sortedArrayToBST(vector<int>&arr){intn=arr.size();if(n==0)returnnullptr;intmid=(n-1)/2;Node*root=newNode(arr[mid]);queue<Data>q;q.push(Data(root,0,n-1));while(!q.empty()){Datad=q.front();q.pop();Node*curr=d.node;intst=d.start,en=d.end;mid=(st+en)/2;// if left subtree existsif(st<mid){intleftVal=(st+mid-1)/2;Node*left=newNode(arr[leftVal]);curr->left=left;q.push(Data(left,st,mid-1));}// if right subtree existsif(en>mid){intrightVal=(mid+1+en)/2;Node*right=newNode(arr[rightVal]);curr->right=right;q.push(Data(right,mid+1,en));}}returnroot;}//Driver Code Startsintmain(){vector<int>arr={1,5,9,14,23,27};Node*root=sortedArrayToBST(arr);levelOrder(root);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;importjava.util.List;importjava.util.Queue;importjava.util.LinkedList;// Node structureclassNode{intdata;Nodeleft,right;Node(intdata){this.data=data;this.left=null;this.right=null;}}classPrint{publicintgetHeight(Noderoot,inth){if(root==null)returnh-1;returnMath.max(getHeight(root.left,h+1),getHeight(root.right,h+1));}publicvoidlevelOrder(Noderoot){Queue<List<Object>>queue=newLinkedList<>();queue.offer(List.of(root,0));intlastLevel=0;// function to get the height of treeintheight=getHeight(root,0);// printing the level order of treewhile(!queue.isEmpty()){List<Object>top=queue.poll();Nodenode=(Node)top.get(0);intlvl=(int)top.get(1);if(lvl>lastLevel){System.out.println();lastLevel=lvl;}// all levels are printedif(lvl>height)break;// printing null nodeSystem.out.print((node.data==-1?"N":node.data)+" ");// null node has no childrenif(node.data==-1)continue;if(node.left==null)queue.offer(List.of(newNode(-1),lvl+1));elsequeue.offer(List.of(node.left,lvl+1));if(node.right==null)queue.offer(List.of(newNode(-1),lvl+1));elsequeue.offer(List.of(node.right,lvl+1));}}}//Driver Code Ends// helper class to store {node, start, end}classData{Nodenode;intstart,end;Data(Nodenode,intstart,intend){this.node=node;this.start=start;this.end=end;}}classGFG{staticNodesortedArrayToBST(int[]arr){intn=arr.length;if(n==0)returnnull;// create the root node.intmid=(n-1)/2;Noderoot=newNode(arr[mid]);Queue<Data>q=newLinkedList<>();q.add(newData(root,0,n-1));while(!q.isEmpty()){Datad=q.poll();Nodecurr=d.node;intst=d.start,en=d.end;mid=(st+en)/2;// if left subtree existsif(st<mid){intleftVal=(st+mid-1)/2;Nodeleft=newNode(arr[leftVal]);curr.left=left;q.add(newData(left,st,mid-1));}// if right subtree existsif(en>mid){intrightVal=(mid+1+en)/2;Noderight=newNode(arr[rightVal]);curr.right=right;q.add(newData(right,mid+1,en));}}returnroot;}//Driver Code Startspublicstaticvoidmain(String[]args){int[]arr={1,5,9,14,23,27};Noderoot=sortedArrayToBST(arr);Printprint=newPrint();print.levelOrder(root);}}//Driver Code Ends
Python
#Driver Code Startsfromcollectionsimportdeque# Node structureclassNode:def__init__(self,data):self.data=dataself.left=Noneself.right=NonedefgetHeight(root,h):ifrootisNone:returnh-1returnmax(getHeight(root.left,h+1),getHeight(root.right,h+1))deflevelOrder(root):queue=deque([[root,0]])lastLevel=0# function to get the height of treeheight=getHeight(root,0)# printing the level order of treewhilequeue:node,lvl=queue.popleft()iflvl>lastLevel:print()lastLevel=lvl# all levels are printediflvl>height:break# printing null nodeprint("N"ifnode.data==-1elsenode.data,end=" ")# null node has no childrenifnode.data==-1:continueifnode.leftisNone:queue.append([Node(-1),lvl+1])else:queue.append([node.left,lvl+1])ifnode.rightisNone:queue.append([Node(-1),lvl+1])else:queue.append([node.right,lvl+1])#Driver Code Ends# helper class to store {node, start, end}classData:def__init__(self,node,start,end):self.node=nodeself.start=startself.end=enddefsortedArrayToBST(arr):n=len(arr)ifn==0:returnNonemid=(n-1)//2root=Node(arr[mid])q=deque([Data(root,0,n-1)])whileq:d=q.popleft()curr=d.nodest,en=d.start,d.endmid=(st+en)//2# if left subtree existsifst<mid:leftVal=(st+mid-1)//2left=Node(arr[leftVal])curr.left=leftq.append(Data(left,st,mid-1))# if right subtree existsifen>mid:rightVal=(mid+1+en)//2right=Node(arr[rightVal])curr.right=rightq.append(Data(right,mid+1,en))returnroot#Driver Code Startsif__name__=="__main__":arr=[1,5,9,14,23,27]root=sortedArrayToBST(arr)levelOrder(root)#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;// Node structureclassNode{publicintdata;publicNodeleft,right;publicNode(intdata){this.data=data;this.left=this.right=null;}}classPrint{publicintGetHeight(Noderoot,inth){if(root==null)returnh-1;returnMath.Max(GetHeight(root.left,h+1),GetHeight(root.right,h+1));}publicvoidlevelOrder(Noderoot){Queue<(Node,int)>queue=newQueue<(Node,int)>();queue.Enqueue((root,0));intlastLevel=0;// function to get the height of treeintheight=GetHeight(root,0);// printing the level order of treewhile(queue.Count>0){var(node,lvl)=queue.Dequeue();if(lvl>lastLevel){Console.WriteLine();lastLevel=lvl;}// all levels are printedif(lvl>height)break;// printing null nodeConsole.Write((node.data==-1?"N":node.data.ToString())+" ");// null node has no childrenif(node.data==-1)continue;if(node.left==null)queue.Enqueue((newNode(-1),lvl+1));elsequeue.Enqueue((node.left,lvl+1));if(node.right==null)queue.Enqueue((newNode(-1),lvl+1));elsequeue.Enqueue((node.right,lvl+1));}}}//Driver Code Ends// helper class to store {node, start, end}classData{publicNodenode;publicintstart,end;publicData(Nodenode,intstart,intend){this.node=node;this.start=start;this.end=end;}}classGFG{staticNodesortedArrayToBST(int[]arr){intn=arr.Length;if(n==0)returnnull;intmid=(n-1)/2;Noderoot=newNode(arr[mid]);Queue<Data>q=newQueue<Data>();q.Enqueue(newData(root,0,n-1));while(q.Count>0){Datad=q.Dequeue();Nodecurr=d.node;intst=d.start,en=d.end;mid=(st+en)/2;// if left subtree existsif(st<mid){intleftVal=(st+mid-1)/2;Nodeleft=newNode(arr[leftVal]);curr.left=left;q.Enqueue(newData(left,st,mid-1));}// if right subtree existsif(en>mid){intrightVal=(mid+1+en)/2;Noderight=newNode(arr[rightVal]);curr.right=right;q.Enqueue(newData(right,mid+1,en));}}returnroot;}//Driver Code StartsstaticvoidMain(){int[]arr={1,5,9,14,23,27};Noderoot=sortedArrayToBST(arr);Printprint=newPrint();print.levelOrder(root);}}//Driver Code Ends
JavaScript
//Driver Code Starts// Node structureclassNode{constructor(data){this.data=data;this.left=null;this.right=null;}}// Custom Queue ImplementationclassQueue{constructor(){this.items={};this.headIndex=0;this.tailIndex=0;}enqueue(item){this.items[this.tailIndex]=item;this.tailIndex++;}dequeue(){if(this.isEmpty())returnnull;letitem=this.items[this.headIndex];deletethis.items[this.headIndex];this.headIndex++;returnitem;}isEmpty(){returnthis.tailIndex===this.headIndex;}size(){returnthis.tailIndex-this.headIndex;}}functiongetHeight(root,h){if(root===null)returnh-1;returnMath.max(getHeight(root.left,h+1),getHeight(root.right,h+1));}functionlevelOrder(root){letq=newQueue();q.enqueue([root,0]);letlastLevel=0;// function to get the height of treeletheight=getHeight(root,0);// printing the level order of treewhile(!q.isEmpty()){let[node,lvl]=q.dequeue();if(lvl>lastLevel){console.log("");lastLevel=lvl;}// all levels are printedif(lvl>height)break;// printing null nodeprocess.stdout.write((node.data===-1?"N":node.data)+" ");// null node has no childrenif(node.data===-1)continue;if(node.left===null)q.enqueue([newNode(-1),lvl+1]);elseq.enqueue([node.left,lvl+1]);if(node.right===null)q.enqueue([newNode(-1),lvl+1]);elseq.enqueue([node.right,lvl+1]);}}//Driver Code Ends// helper object to store {node, start, end}classData{constructor(node,start,end){this.node=node;this.start=start;this.end=end;}}functionsortedArrayToBST(arr){letn=arr.length;if(n===0)returnnull;letmid=Math.floor((n-1)/2);letroot=newNode(arr[mid]);letq=newQueue();q.enqueue(newData(root,0,n-1));while(!q.isEmpty()){letd=q.dequeue();letcurr=d.node;letst=d.start,en=d.end;mid=Math.floor((st+en)/2);// if left subtree existsif(st<mid){letleftVal=Math.floor((st+mid-1)/2);letleft=newNode(arr[leftVal]);curr.left=left;q.enqueue(newData(left,st,mid-1));}// if right subtree existsif(en>mid){letrightVal=Math.floor((mid+1+en)/2);letright=newNode(arr[rightVal]);curr.right=right;q.enqueue(newData(right,mid+1,en));}}returnroot;}//Driver Code Starts// Driver codeconstarr=[1,5,9,14,23,27];constroot=sortedArrayToBST(arr);levelOrder(root);//Driver Code Ends