Given a Doubly Linked List which has data members sorted in ascending order. Construct a Balanced Binary Search Tree which has same data members as the given Doubly Linked List. The tree must be constructed in-place (No new node should be allocated for tree conversion)
Examples:
Input: Doubly Linked List 1 2 3
Output: A Balanced BST
2
/ \
1 3
Input: Doubly Linked List 1 2 3 4 5 6 7
Output: A Balanced BST
4
/ \
2 6
/ \ / \
1 3 5 7
Input: Doubly Linked List 1 2 3 4
Output: A Balanced BST
3
/ \
2 4
/
1
Input: Doubly Linked List 1 2 3 4 5 6
Output: A Balanced BST
4
/ \
2 6
/ \ /
1 3 5
The Doubly Linked List conversion is very much similar to this Singly Linked List problem and the method 1 is exactly same as the method 1 of previous post. Method 2 is also almost same. The only difference in method 2 is, instead of allocating new nodes for BST, we reuse same DLL nodes. We use prev pointer as left and next pointer as right.
Method 1 (Simple)
Following is a simple algorithm where we first find the middle node of list and make it root of the tree to be constructed.
1) Get the Middle of the linked list and make it root.
2) Recursively do same for left half and right half.
a) Get the middle of left half and make it left child of the root
created in step 1.
b) Get the middle of right half and make it right child of the
root created in step 1.
Time complexity: O(nLogn) where n is the number of nodes in Linked List.
Method 2 (Tricky)
The method 1 constructs the tree from root to leaves. In this method, we construct from leaves to root. The idea is to insert nodes in BST in the same order as they appear in Doubly Linked List, so that the tree can be constructed in O(n) time complexity. We first count the number of nodes in the given Linked List. Let the count be n. After counting nodes, we take left n/2 nodes and recursively construct the left subtree. After left subtree is constructed, we assign middle node to root and link the left subtree with root. Finally, we recursively construct the right subtree and link it with root.
While constructing the BST, we also keep moving the list head pointer to next so that we have the appropriate pointer in each recursive call.
Following is the implementation of method 2. The main code which creates Balanced BST is highlighted.
C++
#include <bits/stdc++.h>
using namespace std;
class Node
{
public :
int data;
Node* next;
Node* prev;
};
int countNodes(Node *head);
Node* sortedListToBSTRecur(Node **head_ref, int n);
Node* sortedListToBST(Node *head)
{
int n = countNodes(head);
return sortedListToBSTRecur(&head, n);
}
Node* sortedListToBSTRecur(Node **head_ref, int n)
{
if (n <= 0)
return NULL;
Node *left = sortedListToBSTRecur(head_ref, n/2);
Node *root = *head_ref;
root->prev = left;
*head_ref = (*head_ref)->next;
root->next = sortedListToBSTRecur(head_ref, n-n/2-1);
return root;
}
int countNodes(Node *head)
{
int count = 0;
Node *temp = head;
while (temp)
{
temp = temp->next;
count++;
}
return count;
}
void push(Node** head_ref, int new_data)
{
Node* new_node = new Node();
new_node->data = new_data;
new_node->prev = NULL;
new_node->next = (*head_ref);
if ((*head_ref) != NULL)
(*head_ref)->prev = new_node ;
(*head_ref) = new_node;
}
void printList(Node *node)
{
while (node!=NULL)
{
cout<<node->data<< " " ;
node = node->next;
}
}
void preOrder(Node* node)
{
if (node == NULL)
return ;
cout<<node->data<< " " ;
preOrder(node->prev);
preOrder(node->next);
}
int main()
{
Node* head = NULL;
push(&head, 7);
push(&head, 6);
push(&head, 5);
push(&head, 4);
push(&head, 3);
push(&head, 2);
push(&head, 1);
cout<< "Given Linked List\n" ;
printList(head);
Node *root = sortedListToBST(head);
cout<< "\nPreOrder Traversal of constructed BST \n " ;
preOrder(root);
return 0;
}
|
C
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node* next;
struct Node* prev;
};
int countNodes( struct Node *head);
struct Node* sortedListToBSTRecur( struct Node **head_ref, int n);
struct Node* sortedListToBST( struct Node *head)
{
int n = countNodes(head);
return sortedListToBSTRecur(&head, n);
}
struct Node* sortedListToBSTRecur( struct Node **head_ref, int n)
{
if (n <= 0)
return NULL;
struct Node *left = sortedListToBSTRecur(head_ref, n/2);
struct Node *root = *head_ref;
root->prev = left;
*head_ref = (*head_ref)->next;
root->next = sortedListToBSTRecur(head_ref, n-n/2-1);
return root;
}
int countNodes( struct Node *head)
{
int count = 0;
struct Node *temp = head;
while (temp)
{
temp = temp->next;
count++;
}
return count;
}
void push( struct Node** head_ref, int new_data)
{
struct Node* new_node =
( struct Node*) malloc ( sizeof ( struct Node));
new_node->data = new_data;
new_node->prev = NULL;
new_node->next = (*head_ref);
if ((*head_ref) != NULL)
(*head_ref)->prev = new_node ;
(*head_ref) = new_node;
}
void printList( struct Node *node)
{
while (node!=NULL)
{
printf ( "%d " , node->data);
node = node->next;
}
}
void preOrder( struct Node* node)
{
if (node == NULL)
return ;
printf ( "%d " , node->data);
preOrder(node->prev);
preOrder(node->next);
}
int main()
{
struct Node* head = NULL;
push(&head, 7);
push(&head, 6);
push(&head, 5);
push(&head, 4);
push(&head, 3);
push(&head, 2);
push(&head, 1);
printf ( "Given Linked List\n" );
printList(head);
struct Node *root = sortedListToBST(head);
printf ( "\n PreOrder Traversal of constructed BST \n " );
preOrder(root);
return 0;
}
|
Java
class Node
{
int data;
Node next, prev;
Node( int d)
{
data = d;
next = prev = null ;
}
}
class LinkedList
{
Node head;
Node sortedListToBST()
{
int n = countNodes(head);
return sortedListToBSTRecur(n);
}
Node sortedListToBSTRecur( int n)
{
if (n <= 0 )
return null ;
Node left = sortedListToBSTRecur(n / 2 );
Node root = head;
root.prev = left;
head = head.next;
root.next = sortedListToBSTRecur(n - n / 2 - 1 );
return root;
}
int countNodes(Node head)
{
int count = 0 ;
Node temp = head;
while (temp != null )
{
temp = temp.next;
count++;
}
return count;
}
void push( int new_data)
{
Node new_node = new Node(new_data);
new_node.prev = null ;
new_node.next = head;
if (head != null )
head.prev = new_node;
head = new_node;
}
void printList()
{
Node node = head;
while (node != null )
{
System.out.print(node.data + " " );
node = node.next;
}
}
void preOrder(Node node)
{
if (node == null )
return ;
System.out.print(node.data + " " );
preOrder(node.prev);
preOrder(node.next);
}
public static void main(String[] args)
{
LinkedList llist = new LinkedList();
llist.push( 7 );
llist.push( 6 );
llist.push( 5 );
llist.push( 4 );
llist.push( 3 );
llist.push( 2 );
llist.push( 1 );
System.out.println( "Given Linked List " );
llist.printList();
Node root = llist.sortedListToBST();
System.out.println( "" );
System.out.println( "Pre-Order Traversal of constructed BST " );
llist.preOrder(root);
}
}
|
Python3
class Node:
def __init__( self , data):
self .data = data
self . next = None
self .prev = None
class LinkedList:
def __init__( self ):
self .head = None
def sortedListToBST( self ):
n = self .countNodes( self .head)
return self .sortedListToBSTRecur(n)
def sortedListToBSTRecur( self , n):
if n < = 0 :
return None
left = self .sortedListToBSTRecur(n / / 2 )
root = self .head
root.prev = left
self .head = self .head. next
root. next = self .sortedListToBSTRecur(n - n / / 2 - 1 )
return root
def countNodes( self , head):
count = 0
temp = head
while temp ! = None :
temp = temp. next
count + = 1
return count
def push( self , new_data):
new_node = Node(new_data)
new_node.prev = None
new_node. next = self .head
if self .head ! = None :
self .head.prev = new_node;
self .head = new_node;
def printList( self ):
node = self .head;
while node ! = None :
print (node.data, end = " " )
node = node. next
def preOrder( self , node):
if node = = None :
return
print (node.data, end = " " )
self .preOrder(node.prev)
self .preOrder(node. next )
if __name__ = = '__main__' :
llist = LinkedList()
llist.push( 7 );
llist.push( 6 )
llist.push( 5 )
llist.push( 4 )
llist.push( 3 )
llist.push( 2 )
llist.push( 1 )
print ( "Given Linked List " )
llist.printList()
root = llist.sortedListToBST()
print ("")
print ( "Pre-Order Traversal of constructed BST " )
llist.preOrder(root);
|
C#
using System;
public class Node {
public int data;
public Node next, prev;
public Node( int d) {
data = d;
next = prev = null ;
}
}
public class List {
Node head;
Node sortedListToBST() {
int n = countNodes(head);
return sortedListToBSTRecur(n);
}
Node sortedListToBSTRecur( int n) {
if (n <= 0)
return null ;
Node left = sortedListToBSTRecur(n / 2);
Node root = head;
root.prev = left;
head = head.next;
root.next = sortedListToBSTRecur(n - n / 2 - 1);
return root;
}
int countNodes(Node head) {
int count = 0;
Node temp = head;
while (temp != null ) {
temp = temp.next;
count++;
}
return count;
}
void Push( int new_data) {
Node new_node = new Node(new_data);
new_node.prev = null ;
new_node.next = head;
if (head != null )
head.prev = new_node;
head = new_node;
}
void printList() {
Node node = head;
while (node != null ) {
Console.Write(node.data + " " );
node = node.next;
}
}
void preOrder(Node node) {
if (node == null )
return ;
Console.Write(node.data + " " );
preOrder(node.prev);
preOrder(node.next);
}
public static void Main(String[] args) {
List llist = new List();
llist.Push(7);
llist.Push(6);
llist.Push(5);
llist.Push(4);
llist.Push(3);
llist.Push(2);
llist.Push(1);
Console.WriteLine( "Given Linked List " );
llist.printList();
Node root = llist.sortedListToBST();
Console.WriteLine( "" );
Console.WriteLine( "Pre-Order Traversal of constructed BST " );
llist.preOrder(root);
}
}
|
Javascript
<script>
class Node
{
constructor(d)
{
this .data=d;
this .next= this .prev= null ;
}
}
let head;
function sortedListToBST()
{
let n = countNodes(head);
return sortedListToBSTRecur(n);
}
function sortedListToBSTRecur(n)
{
if (n <= 0)
return null ;
let left = sortedListToBSTRecur(Math.floor(n / 2));
let root = head;
root.prev = left;
head = head.next;
root.next = sortedListToBSTRecur(n - Math.floor(n / 2) - 1);
return root;
}
function countNodes(head)
{
let count = 0;
let temp = head;
while (temp != null )
{
temp = temp.next;
count++;
}
return count;
}
function push(new_data)
{
let new_node = new Node(new_data);
new_node.prev = null ;
new_node.next = head;
if (head != null )
head.prev = new_node;
head = new_node;
}
function printList()
{
let node = head;
while (node != null )
{
document.write(node.data + " " );
node = node.next;
}
}
function preOrder(node)
{
if (node == null )
return ;
document.write(node.data + " " );
preOrder(node.prev);
preOrder(node.next);
}
push(7);
push(6);
push(5);
push(4);
push(3);
push(2);
push(1);
document.write( "Given Linked List <br>" );
printList();
let root = sortedListToBST();
document.write( "<br>" );
document.write( "Pre-Order Traversal of constructed BST <br>" );
preOrder(root);
</script>
|
Output
Given Linked List
1 2 3 4 5 6 7
PreOrder Traversal of constructed BST
4 2 1 3 6 5 7
Time Complexity: O(n)
Auxiliary Space: O(1)
Another Approach(using extra space):
Follow the below steps to solve this problem:
1) Create a array and store all the elements of linked list.
2) Now find the middle element of the linked list and create it root of the tree and call for left array and right array for left and right child.
3) Now recursively repeat above approach until the start becomes greater than end.
4) Now print the preorder traversal of created tree.
Below is the implementation of above approach:
C++
#include<bits/stdc++.h>
using namespace std;
struct LNode{
int data;
LNode* next;
LNode* prev;
};
struct TNode{
int data;
TNode* left;
TNode* right;
TNode( int data){
this ->data = data;
this ->left = NULL;
this ->right = NULL;
}
};
void push(LNode** head_ref, int new_data){
LNode* new_node = new LNode();
new_node->data = new_data;
new_node->prev = NULL;
new_node->next = (*head_ref);
if (*head_ref != NULL)
(*head_ref)->prev = new_node;
*head_ref = new_node;
}
void printList(LNode* node){
while (node != NULL){
cout<<node->data<< " " ;
node = node->next;
}
}
void preOrder(TNode* root){
if (root == NULL) return ;
cout<<root->data<< " " ;
preOrder(root->left);
preOrder(root->right);
}
TNode* sortedListToBSTRecur(vector< int >& vec, int start, int end){
if (start > end) return NULL;
int mid = start + (end-start)/2;
if ((end - start)%2 != 0) mid = mid+1;
TNode* root = new TNode(vec[mid]);
root->left = sortedListToBSTRecur(vec, start, mid-1);
root->right = sortedListToBSTRecur(vec, mid+1, end);
return root;
}
TNode* sortedListToBST(LNode* head){
vector< int > vec;
LNode* temp = head;
while (temp != NULL){
vec.push_back(temp->data);
temp = temp->next;
}
return sortedListToBSTRecur(vec, 0, vec.size()-1);
}
int main(){
LNode* head = NULL;
push(&head, 7);
push(&head, 6);
push(&head, 5);
push(&head, 4);
push(&head, 3);
push(&head, 2);
push(&head, 1);
cout<< "Given Linked List: " <<endl;
printList(head);
cout<<endl;
TNode* root = sortedListToBST(head);
cout<< "Peorder Traversal of constructed BST: " <<endl;
preOrder(root);
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.List;
class LNode {
int data;
LNode next;
LNode prev;
}
class TNode {
int data;
TNode left;
TNode right;
TNode( int item) {
data = item;
left = null ;
right = null ;
}
}
class Main {
static LNode push(LNode head_ref, int new_data) {
LNode new_node = new LNode();
new_node.data = new_data;
new_node.prev = null ;
new_node.next = head_ref;
if (head_ref != null )
head_ref.prev = new_node;
head_ref = new_node;
return head_ref;
}
static void printList(LNode node) {
while (node != null ) {
System.out.print(node.data + " " );
node = node.next;
}
}
static void preOrder(TNode root) {
if (root == null )
return ;
System.out.print(root.data + " " );
preOrder(root.left);
preOrder(root.right);
}
static TNode sortedListToBSTRecur(List<Integer> vec, int start, int end) {
if (start > end)
return null ;
int mid = (start + end) / 2 ;
if ((end - start) % 2 != 0 )
mid = mid + 1 ;
TNode root = new TNode(vec.get(mid));
root.left = sortedListToBSTRecur(vec, start, mid - 1 );
root.right = sortedListToBSTRecur(vec, mid + 1 , end);
return root;
}
static TNode sortedListToBST(LNode head) {
List<Integer> vec = new ArrayList<Integer>();
LNode temp = head;
while (temp != null ) {
vec.add(temp.data);
temp = temp.next;
}
return sortedListToBSTRecur(vec, 0 , vec.size() - 1 );
}
public static void main(String[] args) {
LNode head = null ;
head = push(head, 7 );
head = push(head, 6 );
head = push(head, 5 );
head = push(head, 4 );
head = push(head, 3 );
head = push(head, 2 );
head = push(head, 1 );
System.out.print( "Given Linked List: " );
printList(head);
System.out.println();
TNode root = sortedListToBST(head);
System.out.print( "Preorder traversal of constructed BST: " );
preOrder(root);
}
}
|
Python
class LNode:
def __init__( self , data):
self .data = data
self . next = None
self .prev = None
class TNode:
def __init__( self , data):
self .data = data
self .left = None
self .right = None
def push(head_ref, new_data):
new_node = LNode(new_data)
new_node. next = head_ref
if (head_ref is not None ):
head_ref.prev = new_node
head_ref = new_node
return head_ref
def printList(node):
while (node is not None ):
print (node.data)
node = node. next
def preOrder(root):
if (root is None ):
return
print (root.data)
preOrder(root.left)
preOrder(root.right)
def sortedListToBSTRecur(vec, start, end):
if (start > end):
return None
mid = start + ( int )((end - start) / 2 )
if ((end - start) % 2 ! = 0 ):
mid = mid + 1
root = TNode(vec[mid])
root.left = sortedListToBSTRecur(vec, start, mid - 1 )
root.right = sortedListToBSTRecur(vec, mid + 1 , end)
return root
def sortedListToBST(head):
vec = []
temp = head
while (temp is not None ):
vec.append(temp.data)
temp = temp. next
return sortedListToBSTRecur(vec, 0 , len (vec) - 1 )
head = None
head = push(head, 7 )
head = push(head, 6 )
head = push(head, 5 )
head = push(head, 4 )
head = push(head, 3 )
head = push(head, 2 )
head = push(head, 1 )
print ( "Given Linked List : " )
printList(head)
root = sortedListToBST(head)
print ( "PreOrder traversal of constructed BST : " )
preOrder(root)
|
C#
using System;
using System.Collections.Generic;
public class LNode{
public int data;
public LNode next;
public LNode prev;
}
public class TNode{
public int data;
public TNode left;
public TNode right;
public TNode( int item){
data = item;
left = null ;
right = null ;
}
}
class GFG{
static LNode push(LNode head_ref, int new_data){
LNode new_node = new LNode();
new_node.data = new_data;
new_node.prev = null ;
new_node.next = head_ref;
if (head_ref != null )
head_ref.prev = new_node;
head_ref = new_node;
return head_ref;
}
static void printList(LNode node){
while (node != null ){
Console.Write(node.data + " " );
node = node.next;
}
}
static void preOrder(TNode root){
if (root == null ) return ;
Console.Write(root.data + " " );
preOrder(root.left);
preOrder(root.right);
}
static TNode sortedListToBSTRecur(List< int > vec, int start, int end){
if (start > end) return null ;
int mid = start + (end-start)/2;
if ((end-start)%2 != 0) mid = mid+1;
TNode root = new TNode(vec[mid]);
root.left = sortedListToBSTRecur(vec, start, mid-1);
root.right = sortedListToBSTRecur(vec, mid+1, end);
return root;
}
static TNode sortedListToBST(LNode head){
List< int > vec = new List< int >();
LNode temp = head;
while (temp != null ){
vec.Add(temp.data);
temp = temp.next;
}
return sortedListToBSTRecur(vec, 0, vec.Count-1);
}
public static void Main(String[] args){
LNode head = null ;
head = push(head, 7);
head = push(head, 6);
head = push(head, 5);
head = push(head, 4);
head = push(head, 3);
head = push(head, 2);
head = push(head, 1);
Console.WriteLine( "Given Linked List : " );
printList(head);
Console.WriteLine( "" );
TNode root = sortedListToBST(head);
Console.WriteLine( "Preorder traversal of constructed BST : " );
preOrder(root);
}
}
|
Javascript
class LNode{
constructor(data){
this .data = data;
this .next = null ;
this .prev = null ;
}
}
class TNode{
constructor(data){
this .data =data;
this .left = null ;
this .right = null ;
}
}
function push(head_ref, new_data){
let new_node = new LNode(new_data);
new_node.next = head_ref;
if (head_ref != null ){
head_ref.prev = new_node;
}
head_ref = new_node;
return head_ref;
}
function printList(node){
while (node != null ){
console.log(node.data + " " );
node = node.next;
}
}
function preOrder(root){
if (root == null ) return ;
console.log(root.data + " " );
preOrder(root.left);
preOrder(root.right);
}
function sortedListToBSTRecur(vec, start, end){
if (start > end) return null ;
let mid = start + (end-start)/2;
if ((end - start)%2 != 0) mid = mid+1;
let root = new TNode(vec[mid]);
root.left = sortedListToBSTRecur(vec, start, mid-1);
root.right = sortedListToBSTRecur(vec, mid+1, end);
return root;
}
function sortedListToBST(head){
let vec = [];
let temp = head;
while (temp != null ){
vec.push(temp.data);
temp = temp.next;
}
return sortedListToBSTRecur(vec, 0, vec.length - 1);
}
let head = null ;
head = push(head, 7);
head = push(head, 6);
head = push(head, 5);
head = push(head, 4);
head = push(head, 3);
head = push(head, 2);
head = push(head, 1);
console.log( "Given linked list : " );
printList(head);
let root = sortedListToBST(head);
console.log( "Preorder Traversal of constructed BST: " );
preOrder(root);
|
Output
Given Linked List:
1 2 3 4 5 6 7
Peorder Traversal of constructed BST:
4 2 1 3 6 5 7
Time Complexity: O(N) where N is the number of nodes in given doubly linked list.
Auxiliary Space: O(N) due the extra space.
Please write comments if you find anything incorrect, or if you want to share more information about the topic discussed above.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!