Merge two BSTs

Last Updated : 1 Aug, 2026

Given the roots r1 and r2 of two Binary Search Trees (BSTs), merge the elements of both trees into a single sorted array and return it.

The returned array should contain all the elements from both BSTs, including duplicate values if they are present.

Examples:

Input:  r1 = [3, 1, 5], r2 = [4, 2, 6]

420046852

Output: [1, 2, 3, 4, 5, 6]
Explanation: The inorder traversals of the two BSTs are [1, 3, 5] and [2, 4, 6]. Merging these two sorted sequences gives [1, 2, 3, 4, 5, 6].

Input: r1 = [8, 2, 10, 1, N], r2 = [5, 3, N, 0, N]

420046853

Output: [0, 1, 2, 3, 5, 8, 10] 
Explanation: The inorder traversals of the two BSTs are [1, 2, 8, 10] and [0, 3, 5]. Merging these two sorted sequences gives [0, 1, 2, 3, 5, 8, 10].

Try It Yourself
redirect icon

[Approach - 1] Using Array - O(n + m) Time and O(n + m) Space

The idea is to perform inorder traversal of both BSTs to get their elements in sorted order, store them in two arrays (or lists), and then merge these two sorted arrays using a two-pointer approach to produce a single sorted list containing all elements from both BSTs.

C++
#include<iostream>
#include<vector>
using namespace std;

// Node structure
class Node {
public:
    int data;
    Node* left, *right;
    Node (int x) {
        data = x;
        left = nullptr;
        right = nullptr;
    }
};

// Function to perform inorder traversal of a BST
// Stores elements in sorted order in the given vector
void inorder(Node* root, vector<int>& arr) {
    if (!root) return;
    inorder(root->left, arr);
    arr.push_back(root->data);
    inorder(root->right, arr);
}

// Function to merge two sorted arrays into one sorted array
vector<int> mergeArrays(vector<int>& arr1, vector<int>& arr2) {
    vector<int> result;
    int i = 0, j = 0;
    
    // Traverse both arrays and pick the smaller element
    while (i < arr1.size() && j < arr2.size()) {
        if (arr1[i] <= arr2[j]) {
            result.push_back(arr1[i++]);
        } 
        else {
            result.push_back(arr2[j++]);
        }
    }
    
    while (i < arr1.size()) result.push_back(arr1[i++]);
    
    while (j < arr2.size()) result.push_back(arr2[j++]);
    
    return result;
}

// Function to merge elements of two BSTs into a single sorted list
vector<int> merge(Node *root1, Node *root2) {
    vector<int> arr1, arr2;
    
    // Get inorder traversal of both BSTs
    inorder(root1, arr1);
    inorder(root2, arr2);
    
    return mergeArrays(arr1, arr2);
}

int main() {
    
    // Create binary tree 1
    //           3
    //         /   \
    //       1      5
    Node* root1 = new Node(3);
    root1->left = new Node(1);
    root1->right = new Node(5);
    
    // Create binary tree 2
    //           4
    //         /   \
    //       2      6
    Node* root2 = new Node(4);
    root2->left = new Node(2);
    root2->right = new Node(6);
    
    vector<int> res = merge(root1, root2);
    
    // Print the array.
    cout << "[";
    for (int i = 0; i < res.size(); i++)
    {
        cout << res[i];
        if (i != res.size() - 1)
            cout << ", ";
    }
    cout << "]";
    return 0;
}
Java
import java.util.ArrayList;

// Node structure
class Node {
    int data;
    Node left, right;
    Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GFG {
    
    // Function to perform inorder traversal of a BST
    // Stores elements in sorted order in the given list
    static void inorder(Node root, ArrayList<Integer> arr) {
        if (root == null) return;
        inorder(root.left, arr);
        arr.add(root.data);
        inorder(root.right, arr);
    }
    
    // Function to merge two sorted lists into one sorted list
    static ArrayList<Integer> mergeArrays(ArrayList<Integer> arr1, 
                                          ArrayList<Integer> arr2) {
        ArrayList<Integer> result = new ArrayList<>();
        int i = 0, j = 0;
        
        // Traverse both lists and pick the smaller element
        while (i < arr1.size() && j < arr2.size()) {
            if (arr1.get(i) <= arr2.get(j)) {
                result.add(arr1.get(i++));
            } 
            else {
                result.add(arr2.get(j++));
            }
        }
        
        while (i < arr1.size()) result.add(arr1.get(i++));
        
        while (j < arr2.size()) result.add(arr2.get(j++));
        
        return result;
    }
    
    // Function to merge elements of two BSTs into a single sorted list
    static ArrayList<Integer> merge(Node root1, Node root2) {
        ArrayList<Integer> arr1 = new ArrayList<>();
        ArrayList<Integer> arr2 = new ArrayList<>();
        
        // Get inorder traversal of both BSTs
        inorder(root1, arr1);
        inorder(root2, arr2);
        
        return mergeArrays(arr1, arr2);
    }

    public static void main(String[] args) {
        
        // Create binary tree 1
        //           3
        //         /   \
        //       1      5
        Node root1 = new Node(3);
        root1.left = new Node(1);
        root1.right = new Node(5);
        
        // Create binary tree 2
        //           4
        //         /   \
        //       2      6
        Node root2 = new Node(4);
        root2.left = new Node(2);
        root2.right = new Node(6);
        
        ArrayList<Integer> res = merge(root1, root2);
         System.out.print("[");
        for (int i = 0; i < res.size(); i++) {
            System.out.print(res.get(i));
            if (i != res.size() - 1)
                System.out.print(", ");
        }
        System.out.print("]");
    }
}
Python
#  Node structure
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

# Function to perform inorder traversal of a BST
# Stores elements in sorted order in the given list
def inorder(root, arr):
    if not root:
        return
    inorder(root.left, arr)
    arr.append(root.data)
    inorder(root.right, arr)

# Function to merge two sorted lists into one sorted list
def mergeArrays(arr1, arr2):
    result = []
    i = j = 0
    
    # Traverse both lists and pick the smaller element
    while i < len(arr1) and j < len(arr2):
        if arr1[i] <= arr2[j]:
            result.append(arr1[i])
            i += 1
        else:
            result.append(arr2[j])
            j += 1
            
    while i < len(arr1):
        result.append(arr1[i])
        i += 1
        
    while j < len(arr2):
        result.append(arr2[j])
        j += 1
        
    return result

# Function to merge elements of two BSTs into a single sorted list
def merge(root1, root2):
    arr1, arr2 = [], []
    
    # Get inorder traversal of both BSTs
    inorder(root1, arr1)
    inorder(root2, arr2)
    
    return mergeArrays(arr1, arr2)

if __name__ == "__main__":
    
    # Create binary tree 1
    #           3
    #         /   \
    #       1      5
    root1 = Node(3)
    root1.left = Node(1)
    root1.right = Node(5)
    
    # Create binary tree 2
    #           4
    #         /   \
    #       2      6
    root2 = Node(4)
    root2.left = Node(2)
    root2.right = Node(6)
    
    res = merge(root1, root2)
    # Print the array.
    print("[", end="")
    for i in range(len(res)):
        print(res[i], end="")
        if i != len(res) - 1:
            print(", ", end="")
    print("]")
C#
using System;
using System.Collections.Generic;

// Node structure
class Node {
    public int data;
    public Node left, right;
    public Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GFG {
    
    // Function to perform inorder traversal of a BST
    // Stores elements in sorted order in the given list
    static void inorder(Node root, List<int> arr) {
        if (root == null) return;
        inorder(root.left, arr);
        arr.Add(root.data);
        inorder(root.right, arr);
    }
    
    // Function to merge two sorted lists into one sorted list
    static List<int> mergeArrays(List<int> arr1, List<int> arr2) {
        List<int> result = new List<int>();
        int i = 0, j = 0;
        
        // Traverse both lists and pick the smaller element
        while (i < arr1.Count && j < arr2.Count) {
            if (arr1[i] <= arr2[j]) {
                result.Add(arr1[i++]);
            } 
            else {
                result.Add(arr2[j++]);
            }
        }
        
        while (i < arr1.Count) result.Add(arr1[i++]);
        
        while (j < arr2.Count) result.Add(arr2[j++]);
        
        return result;
    }
    
    // Function to merge elements of two BSTs into a single sorted list
    static List<int> merge(Node root1, Node root2) {
        List<int> arr1 = new List<int>();
        List<int> arr2 = new List<int>();
        
        // Get inorder traversal of both BSTs
        inorder(root1, arr1);
        inorder(root2, arr2);
        
        return mergeArrays(arr1, arr2);
    }

    static void Main() {
        
        // Create binary tree 1
        //           3
        //         /   \
        //       1      5
        Node root1 = new Node(3);
        root1.left = new Node(1);
        root1.right = new Node(5);
        
        // Create binary tree 2
        //           4
        //         /   \
        //       2      6
        Node root2 = new Node(4);
        root2.left = new Node(2);
        root2.right = new Node(6);
        
        List<int> res = merge(root1, root2);
        // Print the array.
        Console.Write("[");
        for (int i = 0; i < res.Count; i++)
        {
            Console.Write(res[i]);
            if (i != res.Count - 1)
                Console.Write(", ");
        }
        Console.Write("]");
    }
}
JavaScript
// Node structure
class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

// Function to perform inorder traversal of a BST
// Stores elements in sorted order in the given array
function inorder(root, arr) {
    if (!root) return;
    inorder(root.left, arr);
    arr.push(root.data);
    inorder(root.right, arr);
}

// Function to merge two sorted arrays into one sorted array
function mergeArrays(arr1, arr2) {
    let result = [];
    let i = 0, j = 0;
    
    // Traverse both arrays and pick the smaller element
    while (i < arr1.length && j < arr2.length) {
        if (arr1[i] <= arr2[j]) {
            result.push(arr1[i++]);
        } 
        else {
            result.push(arr2[j++]);
        }
    }
    
    while (i < arr1.length) result.push(arr1[i++]);
    
    while (j < arr2.length) result.push(arr2[j++]);
    
    return result;
}

// Function to merge elements of two BSTs into a single sorted array
function merge(root1, root2) {
    let arr1 = [], arr2 = [];
    
    // Get inorder traversal of both BSTs
    inorder(root1, arr1);
    inorder(root2, arr2);
    
    return mergeArrays(arr1, arr2);
}

// Driver Code

// Create binary tree 1
//           3
//         /   \
//       1      5
let root1 = new Node(3);
root1.left = new Node(1);
root1.right = new Node(5);

// Create binary tree 2
//           4
//         /   \
//       2      6
let root2 = new Node(4);
root2.left = new Node(2);
root2.right = new Node(6);

let res = merge(root1, root2);
process.stdout.write("[");
    for (let i = 0; i < res.length; i++) {
        process.stdout.write(res[i].toString());
        if (i !== res.length - 1)
            process.stdout.write(", ");
    }
    process.stdout.write("]");

Output
[1, 2, 3, 4, 5, 6]

[Approach - 2] Using Stack - O(n + m) Time and O(n + m) Space

The idea is to perform the inorder traversal of both BSTs simultaneously using two stacks. Since the inorder traversal of a BST generates elements in sorted order, the top of each stack always represents the next smallest unprocessed element of that BST. By comparing these two elements, we can add the smaller one to the result and continue its traversal, thereby merging both BSTs directly into a sorted array.

  • Create two stacks to perform iterative inorder traversal of both BSTs.
  • Push all the left descendants of the current nodes onto their respective stacks.
  • Compare the top nodes of both stacks and remove the smaller one.
  • Add the removed node's value to the result and move to its right child.
  • Repeat the above steps until both stacks become empty.

Why using Stack?

Although recursion can perform the inorder traversal of a BST, it is not suitable here because we need to traverse both BSTs simultaneously and compare their next inorder elements at each step. Using two stacks allows us to pause and resume the traversal of either tree whenever required, making it possible to merge the elements directly into a sorted array without storing the complete inorder traversals.

C++
#include<iostream>
#include<vector>
#include<stack>
using namespace std;

// Node structure
class Node {
public:
    int data;
    Node* left, *right;
    Node (int x) {
        data = x;
        left = nullptr;
        right = nullptr;
    }
};

vector<int> merge(Node *root1, Node *root2) {
    vector<int> res;
    stack<Node*> s1, s2;
    
    while (root1 || root2 || !s1.empty() || !s2.empty()) {
        
        // move to the leftmost nodes(min values)
        while (root1) {
            s1.push(root1);
            root1 = root1->left;
        }
        
        while (root2) {
            s2.push(root2);
            root2 = root2->left;
        }
        
        // compare the top element and remove 
        // it and move to its right child
        if (s2.empty() || (!s1.empty() && s1.top()->data <= s2.top()->data)) {
            root1 = s1.top();
            s1.pop();
            res.push_back(root1->data);
            root1 = root1->right;
        } 
        else {
            root2 = s2.top();
            s2.pop();
            res.push_back(root2->data);
            root2 = root2->right;
        }
    }
    return res;
}

int main() {
    
    // Create binary tree 1
    //           3
    //         /   \
    //       1      5
    Node* root1 = new Node(3);
    root1->left = new Node(1);
    root1->right = new Node(5);
    
    // Create binary tree 2
    //           4
    //         /   \
    //       2      6
    Node* root2 = new Node(4);
    root2->left = new Node(2);
    root2->right = new Node(6);
    
    vector<int> res = merge(root1, root2);
    
    // Print the array.
    cout << "[";
    for (int i = 0; i < res.size(); i++) {
        cout << res[i];
        if (i != res.size() - 1)
            cout << ", ";
    }
    cout << "]";
    return 0;
}
Java
import java.util.ArrayList;
import java.util.Stack;

// Node structure
class Node {
    int data;
    Node left, right;
    Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GFG {
    
    static ArrayList<Integer> merge(Node root1, Node root2) {
        ArrayList<Integer> res = new ArrayList<>();
        Stack<Node> s1 = new Stack<>();
        Stack<Node> s2 = new Stack<>();
        
        while (root1 != null || root2 != null || !s1.empty() || !s2.empty()) {
            
            // move to the leftmost nodes(min values)
            while (root1 != null) {
                s1.push(root1);
                root1 = root1.left;
            }
            while (root2 != null) {
                s2.push(root2);
                root2 = root2.left;
            }
            
            // compare the top element and remove 
            // it and move to its right child
            if (s2.empty() || (!s1.empty() && s1.peek().data <= s2.peek().data)) {
                root1 = s1.pop();
                res.add(root1.data);
                root1 = root1.right;
            } 
            else {
                root2 = s2.pop();
                res.add(root2.data);
                root2 = root2.right;
            }
        }
        return res;
    }

    public static void main(String[] args) {
        
        // Create binary tree 1
        //           3
        //         /   \
        //       1      5
        Node root1 = new Node(3);
        root1.left = new Node(1);
        root1.right = new Node(5);
        
        // Create binary tree 2
        //           4
        //         /   \
        //       2      6
        Node root2 = new Node(4);
        root2.left = new Node(2);
        root2.right = new Node(6);
        
        ArrayList<Integer> res = merge(root1, root2);
        
        // Print the array.
        System.out.print("[");
        for (int i = 0; i < res.size(); i++) {
            System.out.print(res.get(i));
            if (i != res.size() - 1)
                System.out.print(", ");
        }
        System.out.print("]");
    }
}
Python
#  Node structure
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

def merge(root1, root2):
    res = []
    s1 = []
    s2 = []
    
    while root1 or root2 or s1 or s2:
        while root1:
            
            # move to the leftmost nodes(min values)
            s1.append(root1)
            root1 = root1.left
        while root2:
            s2.append(root2)
            root2 = root2.left
        
        #  compare the top element and remove 
        #  it and move to its right child
        if not s2 or (s1 and s1[-1].data <= s2[-1].data):
            root1 = s1.pop()
            res.append(root1.data)
            root1 = root1.right
        else:
            root2 = s2.pop()
            res.append(root2.data)
            root2 = root2.right
    return res

if __name__ == "__main__":
    
    # Create binary tree 1
    #           3
    #         /   \
    #       1      5
    root1 = Node(3)
    root1.left = Node(1)
    root1.right = Node(5)
    
    # Create binary tree 2
    #           4
    #         /   \
    #       2      6
    root2 = Node(4)
    root2.left = Node(2)
    root2.right = Node(6)
    
    res = merge(root1, root2)
    
    # Print the array.
    print("[", end="")
    for i in range(len(res)):
        print(res[i], end="")
        if i != len(res) - 1:
            print(", ", end="")
    print("]")
C#
using System;
using System.Collections.Generic;

// Node structure
class Node {
    public int data;
    public Node left, right;
    public Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GFG {
    
    static List<int> merge(Node root1, Node root2) {
        List<int> res = new List<int>();
        Stack<Node> s1 = new Stack<Node>();
        Stack<Node> s2 = new Stack<Node>();
        
        while (root1 != null || root2 != null || 
        s1.Count > 0 || s2.Count > 0) {
            
            // move to the leftmost nodes(min values)
            while (root1 != null) {
                s1.Push(root1);
                root1 = root1.left;
            }
            while (root2 != null) {
                s2.Push(root2);
                root2 = root2.left;
            }
            
            // compare the top element and remove 
            // it and move to its right child
            if (s2.Count == 0 || (s1.Count > 0 && s1.Peek().data <= s2.Peek().data)) {
                root1 = s1.Pop();
                res.Add(root1.data);
                root1 = root1.right;
            } 
            else {
                root2 = s2.Pop();
                res.Add(root2.data);
                root2 = root2.right;
            }
        }
        return res;
    }

    static void Main() {
        
        // Create binary tree 1
        //           3
        //         /   \
        //       1      5
        Node root1 = new Node(3);
        root1.left = new Node(1);
        root1.right = new Node(5);
        
        // Create binary tree 2
        //           4
        //         /   \
        //       2      6
        Node root2 = new Node(4);
        root2.left = new Node(2);
        root2.right = new Node(6);
        
        List<int> res = merge(root1, root2);
        // Print the array.
        Console.Write("[");
        for (int i = 0; i < res.Count; i++)
        {
            Console.Write(res[i]);
            if (i != res.Count - 1)
                Console.Write(", ");
        }
        Console.Write("]");
    }
}
JavaScript
// Node structure
class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

function merge(root1, root2) {
    let res = [];
    let s1 = [];
    let s2 = [];
    
    while (root1 || root2 || s1.length > 0 || s2.length > 0) {
        while (root1) {
            
            // move to the leftmost nodes(min values)
            s1.push(root1);
            root1 = root1.left;
        }
        while (root2) {
            s2.push(root2);
            root2 = root2.left;
        }
        
        // compare the top element and remove 
        // it and move to its right child
        if (s2.length === 0 || (s1.length > 0 && 
                s1[s1.length-1].data <= s2[s2.length-1].data)) {
            root1 = s1.pop();
            res.push(root1.data);
            root1 = root1.right;
        } 
        else {
            root2 = s2.pop();
            res.push(root2.data);
            root2 = root2.right;
        }
    }
    return res;
}

// Create binary tree 1
//           3
//         /   \
//       1      5
let root1 = new Node(3);
root1.left = new Node(1);
root1.right = new Node(5);

// Create binary tree 2
//           4
//         /   \
//       2      6
let root2 = new Node(4);
root2.left = new Node(2);
root2.right = new Node(6);

let res = merge(root1, root2);

// Print the array.
    process.stdout.write("[");

    for (let i = 0; i < res.length; i++) {
        process.stdout.write(res[i].toString());

        if (i !== res.length - 1)
            process.stdout.write(", ");
    }

    process.stdout.write("]");

Output
[1, 2, 3, 4, 5, 6]
Comment