Cartesian tree from inorder traversal | Segment Tree - GeeksforGeeks

04 Oct, 2021
Given an in-order traversal of a cartesian tree, the task is to build the entire tree from it.
Examples: 
Input: arr[] = {1, 5, 3}
Output: 1 5 3
  5
 / \
1   3

Input: arr[] = {3, 7, 4, 8}
Output: 3 7 4 8
     8
    /
   7
  / \
 3   4
Approach: We have already seen an algorithm here that takes O(NlogN) time on an average but can get to O(N2) in the worst case.In this article, we will see how to build the cartesian in worst case running time of O(Nlog(N)). For this, we will use segment-tree to answer range-max queries.
Below will be our recursive algorithm on range {L, R}:  
Find the maximum in this range {L, R} using range-max query on the segment-tree. Let’s say ‘M’ is index the maximum in the range.Pick up ‘arr[M]’ as the value for current node and create a node with this value.Solve for range {L, M-1} and {M+1, R}.Set the node returned by {L, M-1} as the left child of current node and {M+1, R} as the right child.
Find the maximum in this range {L, R} using range-max query on the segment-tree. Let’s say ‘M’ is index the maximum in the range.
Pick up ‘arr[M]’ as the value for current node and create a node with this value.
Solve for range {L, M-1} and {M+1, R}.
Set the node returned by {L, M-1} as the left child of current node and {M+1, R} as the right child.
Below is the implementation of the above approach:  
C++
Java
Python3
C#
Javascript
// C++ implementation of the approach#include <bits/stdc++.h>using namespace std; #define maxLen 30 // Node of the BSTstruct node {    int data;    node* left;    node* right;    node(int data)    {        left = NULL;        right = NULL;        this->data = data;    }}; // Array to store segment treeint segtree[maxLen * 4]; // Function to create segment-tree to answer// range-max queryint buildTree(int l, int r, int i, int* arr){    // Base case    if (l == r) {        segtree[i] = l;        return l;    }     // Maximum index in left range    int l1 = buildTree(l, (l + r) / 2,                       2 * i + 1, arr);     // Maximum index in right range    int r1 = buildTree((l + r) / 2 + 1,                       r, 2 * i + 2, arr);     // If value at l1 > r1    if (arr[l1] > arr[r1])        segtree[i] = l1;     // Else    else        segtree[i] = r1;     // Returning the maximum in range    return segtree[i];} // Function to answer range max queryint rangeMax(int l, int r, int rl,             int rr, int i, int* arr){     // Base cases    if (r < rl || l > rr)        return -1;    if (l >= rl and r <= rr)        return segtree[i];     // Maximum in left range    int l1 = rangeMax(l, (l + r) / 2, rl,                      rr, 2 * i + 1, arr);     // Maximum in right range    int r1 = rangeMax((l + r) / 2 + 1, r,                      rl, rr, 2 * i + 2, arr);     // l1 = -1 means left range    // was out-side required range    if (l1 == -1)        return r1;    if (r1 == -1)        return l1;     // Returning the maximum    // among two ranges    if (arr[l1] > arr[r1])        return l1;    else        return r1;} // Function to print the inorder// traversal of the binary treevoid inorder(node* curr){     // Base case    if (curr == NULL)        return;     // Traversing the left sub-tree    inorder(curr->left);     // Printing current node    cout << curr->data << " ";     // Traversing the right sub-tree    inorder(curr->right);} // Function to build cartesian treenode* createCartesianTree(int l, int r, int* arr, int n){    // Base case    if (r < l)        return NULL;     // Maximum in the range    int m = rangeMax(0, n - 1, l, r, 0, arr);     // Creating current node    node* curr = new node(arr[m]);     // Creating left sub-tree    curr->left = createCartesianTree(l, m - 1, arr, n);     // Creating right sub-tree    curr->right = createCartesianTree(m + 1, r, arr, n);     // Returning current node    return curr;} // Driver codeint main(){    // In-order traversal of cartesian tree    int arr[] = { 8, 11, 21, 100, 5, 70, 55 };     // Size of the array    int n = sizeof(arr) / sizeof(int);     // Building the segment tree    buildTree(0, n - 1, 0, arr);     // Building and printing cartesian tree    inorder(createCartesianTree(0, n - 1, arr, n));}
// Java implementation of the approachimport java.util.*; class GFG{static int maxLen = 30; // Node of the BSTstatic class node{    int data;    node left;    node right;    node(int data)    {        left = null;        right = null;        this.data = data;    }}; // Array to store segment treestatic int segtree[] = new int[maxLen * 4]; // Function to create segment-tree to answer// range-max querystatic int buildTree(int l, int r,                     int i, int[] arr){    // Base case    if (l == r)    {        segtree[i] = l;        return l;    }     // Maximum index in left range    int l1 = buildTree(l, (l + r) / 2,                       2 * i + 1, arr);     // Maximum index in right range    int r1 = buildTree((l + r) / 2 + 1,                        r, 2 * i + 2, arr);     // If value at l1 > r1    if (arr[l1] > arr[r1])        segtree[i] = l1;     // Else    else        segtree[i] = r1;     // Returning the maximum in range    return segtree[i];} // Function to answer range max querystatic int rangeMax(int l, int r, int rl,                    int rr, int i, int[] arr){     // Base cases    if (r < rl || l > rr)        return -1;    if (l >= rl && r <= rr)        return segtree[i];     // Maximum in left range    int l1 = rangeMax(l, (l + r) / 2, rl,                      rr, 2 * i + 1, arr);     // Maximum in right range    int r1 = rangeMax((l + r) / 2 + 1, r,                       rl, rr, 2 * i + 2, arr);     // l1 = -1 means left range    // was out-side required range    if (l1 == -1)        return r1;    if (r1 == -1)        return l1;     // Returning the maximum    // among two ranges    if (arr[l1] > arr[r1])        return l1;    else        return r1;} // Function to print the inorder// traversal of the binary treestatic void inorder(node curr){     // Base case    if (curr == null)        return;     // Traversing the left sub-tree    inorder(curr.left);     // Printing current node    System.out.print(curr.data + " ");     // Traversing the right sub-tree    inorder(curr.right);} // Function to build cartesian treestatic node createCartesianTree(int l, int r,                                int[] arr, int n){    // Base case    if (r < l)        return null;     // Maximum in the range    int m = rangeMax(0, n - 1, l, r, 0, arr);     // Creating current node    node curr = new node(arr[m]);     // Creating left sub-tree    curr.left = createCartesianTree(l, m - 1, arr, n);     // Creating right sub-tree    curr.right = createCartesianTree(m + 1, r, arr, n);     // Returning current node    return curr;} // Driver codepublic static void main(String args[]){    // In-order traversal of cartesian tree    int arr[] = { 8, 11, 21, 100, 5, 70, 55 };     // Size of the array    int n = arr.length;     // Building the segment tree    buildTree(0, n - 1, 0, arr);     // Building && printing cartesian tree    inorder(createCartesianTree(0, n - 1, arr, n));}} // This code is contributed by Arnab Kundu
# Python3 implementation of the approach # Node of a linked listclass Node:    def __init__(self, data = None, left = None,                right = None ):        self.data = data        self.right = right        self.left = left         maxLen = 30 # Array to store segment treesegtree = [0]*(maxLen * 4) # Function to create segment-tree to answer# range-max querydef buildTree(l , r ,i , arr):     global segtree    global maxLen         # Base case    if (l == r) :             segtree[i] = l        return l         # Maximum index in left range    l1 = buildTree(l, int((l + r) / 2),                   2 * i + 1, arr)     # Maximum index in right range    r1 = buildTree(int((l + r) / 2) + 1,r,                   2 * i + 2, arr)     # If value at l1 > r1    if (arr[l1] > arr[r1]):        segtree[i] = l1     # Else    else:        segtree[i] = r1     # Returning the maximum in range    return segtree[i] # Function to answer range max querydef rangeMax(l, r, rl, rr, i, arr):     global segtree    global maxLen         # Base cases    if (r < rl or l > rr):        return -1    if (l >= rl and r <= rr):        return segtree[i]     # Maximum in left range    l1 = rangeMax(l, int((l + r) / 2), rl,                            rr, 2 * i + 1, arr)     # Maximum in right range    r1 = rangeMax(int((l + r) / 2) + 1, r, rl,                    rr, 2 * i + 2, arr)     # l1 = -1 means left range    # was out-side required range    if (l1 == -1):        return r1    if (r1 == -1):        return l1     # Returning the maximum    # among two ranges    if (arr[l1] > arr[r1]):        return l1    else:        return r1 # Function to print the inorder# traversal of the binary treedef inorder(curr):     # Base case    if (curr == None):        return     # Traversing the left sub-tree    inorder(curr.left)     # Printing current node    print(curr.data, end= " ")     # Traversing the right sub-tree    inorder(curr.right) # Function to build cartesian treedef createCartesianTree(l , r , arr, n):     # Base case    if (r < l):        return None     # Maximum in the range    m = rangeMax(0, n - 1, l, r, 0, arr)     # Creating current node    curr = Node(arr[m])     # Creating left sub-tree    curr.left = createCartesianTree(l, m - 1, arr, n)     # Creating right sub-tree    curr.right = createCartesianTree(m + 1, r, arr, n)     # Returning current node    return curr # Driver code # In-order traversal of cartesian treearr = [ 8, 11, 21, 100, 5, 70, 55 ] # Size of the arrayn = len(arr) # Building the segment treebuildTree(0, n - 1, 0, arr) # Building && printing cartesian treeinorder(createCartesianTree(0, n - 1, arr, n)) # This code is contributed by Arnab Kundu
// C# implementation of the approachusing System; class GFG{    static int maxLen = 30;         // Node of the BST    public class node    {        public int data;        public node left;        public node right;        public node(int data)        {            left = null;            right = null;            this.data = data;        }    };         // Array to store segment tree    static int []segtree = new int[maxLen * 4];         // Function to create segment-tree to answer    // range-max query    static int buildTree(int l, int r,                         int i, int[] arr)    {        // Base case        if (l == r)        {            segtree[i] = l;            return l;        }             // Maximum index in left range        int l1 = buildTree(l, (l + r) / 2,                           2 * i + 1, arr);             // Maximum index in right range        int r1 = buildTree((l + r) / 2 + 1,                            r, 2 * i + 2, arr);             // If value at l1 > r1        if (arr[l1] > arr[r1])            segtree[i] = l1;             // Else        else            segtree[i] = r1;             // Returning the maximum in range        return segtree[i];    }         // Function to answer range max query    static int rangeMax(int l, int r, int rl,                        int rr, int i, int[] arr)    {             // Base cases        if (r < rl || l > rr)            return -1;        if (l >= rl && r <= rr)            return segtree[i];             // Maximum in left range        int l1 = rangeMax(l, (l + r) / 2, rl,                          rr, 2 * i + 1, arr);             // Maximum in right range        int r1 = rangeMax((l + r) / 2 + 1, r,                           rl, rr, 2 * i + 2, arr);             // l1 = -1 means left range        // was out-side required range        if (l1 == -1)            return r1;        if (r1 == -1)            return l1;             // Returning the maximum        // among two ranges        if (arr[l1] > arr[r1])            return l1;        else            return r1;    }         // Function to print the inorder    // traversal of the binary tree    static void inorder(node curr)    {             // Base case        if (curr == null)            return;             // Traversing the left sub-tree        inorder(curr.left);             // Printing current node        Console.Write(curr.data + " ");             // Traversing the right sub-tree        inorder(curr.right);    }         // Function to build cartesian tree    static node createCartesianTree(int l, int r,                                    int[] arr, int n)    {        // Base case        if (r < l)            return null;             // Maximum in the range        int m = rangeMax(0, n - 1, l, r, 0, arr);             // Creating current node        node curr = new node(arr[m]);             // Creating left sub-tree        curr.left = createCartesianTree(l, m - 1,                                         arr, n);             // Creating right sub-tree        curr.right = createCartesianTree(m + 1, r,                                          arr, n);             // Returning current node        return curr;    }         // Driver code    public static void Main()    {        // In-order traversal of cartesian tree        int []arr = { 8, 11, 21, 100, 5, 70, 55 };             // Size of the array        int n = arr.Length;             // Building the segment tree        buildTree(0, n - 1, 0, arr);             // Building && printing cartesian tree        inorder(createCartesianTree(0, n - 1, arr, n));    }} // This code is contributed by AnkitRai01
<script> // Javascript implementation of the approachvar maxLen = 30; // Node of the BSTclass node{    constructor(data)    {        this.data = data;        this.left = null;        this.right = null;    }}; // Array to store segment treevar segtree = Array(maxLen * 4).fill(0); // Function to create segment-tree to answer// range-max queryfunction buildTree(l, r, i, arr){         // Base case    if (l == r)    {        segtree[i] = l;        return l;    }     // Maximum index in left range    var l1 = buildTree(l, parseInt((l + r) / 2),                                2 * i + 1, arr);     // Maximum index in right range    var r1 = buildTree(parseInt((l + r) / 2) + 1,                              r, 2 * i + 2, arr);     // If value at l1 > r1    if (arr[l1] > arr[r1])        segtree[i] = l1;     // Else    else        segtree[i] = r1;     // Returning the maximum in range    return segtree[i];} // Function to answer range max queryfunction rangeMax(l, r, rl, rr, i, arr){         // Base cases    if (r < rl || l > rr)        return -1;    if (l >= rl && r <= rr)        return segtree[i];     // Maximum in left range    var l1 = rangeMax(l, parseInt((l + r) / 2), rl,                               rr, 2 * i + 1, arr);     // Maximum in right range    var r1 = rangeMax(parseInt((l + r) / 2) + 1, r,                        rl, rr, 2 * i + 2, arr);     // l1 = -1 means left range    // was out-side required range    if (l1 == -1)        return r1;    if (r1 == -1)        return l1;     // Returning the maximum    // among two ranges    if (arr[l1] > arr[r1])        return l1;    else        return r1;} // Function to print the inorder// traversal of the binary treefunction inorder(curr){         // Base case    if (curr == null)        return;     // Traversing the left sub-tree    inorder(curr.left);     // Printing current node    document.write(curr.data + " ");     // Traversing the right sub-tree    inorder(curr.right);} // Function to build cartesian treefunction createCartesianTree(l, r, arr, n){         // Base case    if (r < l)        return null;     // Maximum in the range    var m = rangeMax(0, n - 1, l, r, 0, arr);     // Creating current node    var curr = new node(arr[m]);     // Creating left sub-tree    curr.left = createCartesianTree(l, m - 1,                                     arr, n);     // Creating right sub-tree    curr.right = createCartesianTree(m + 1, r,                                      arr, n);     // Returning current node    return curr;} // Driver code // In-order traversal of cartesian treevar arr = [ 8, 11, 21, 100, 5, 70, 55 ]; // Size of the arrayvar n = arr.length; // Building the segment treebuildTree(0, n - 1, 0, arr); // Building && printing cartesian treeinorder(createCartesianTree(0, n - 1, arr, n)); // This code is contributed by noob2000 </script>
8 11 21 100 5 70 55
 
Time complexity: O(N+logN)Auxiliary Space: O(N).  
andrew1234
ankthon
noob2000
pankajsharmagfg
ashutoshsinghgeeksforgeeks
Segment-Tree
Algorithms
Data Structures
Divide and Conquer
Recursion
Tree
Data Structures
Recursion
Divide and Conquer
Tree
Segment-Tree
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
DSA Sheet by Love Babbar
How to Start Learning DSA?
K means Clustering - Introduction
Difference between Algorithm, Pseudocode and Program
Types of Complexity Classes | P, NP, CoNP, NP hard and NP complete
DSA Sheet by Love Babbar
Doubly Linked List | Set 1 (Introduction and Insertion)
How to Start Learning DSA?
Abstract Data Types
Implementing a Linked List in Java using Class