Minimum swap required to convert binary tree to binary search tree

Last Updated : 13 Sep, 2026

Given an array arr[] which represents a Complete Binary Tree i.e, if index i is the parent, index 2*i + 1 is the left child and index 2*i + 2 is the right child. Find the minimum number of swaps required to convert it into a Binary Search Tree.

Examples:  

Input: arr[] = [5, 6, 7, 8, 9, 10, 11]
Output: 3
Explanation:
Binary tree of the given array:

Minimum-swap-required-to-convert-binary-tree-to-binary-search-tree-1

Swap 1: Swap node 8 with node 5.
Swap 2: Swap node 9 with node 10.
Swap 3: Swap node 10 with node 7.
So, minimum 3 swaps are required to obtain the below binary search tree:

Minimum-swap-required-to-convert-binary-tree-to-binary-search-tree-3

Input: arr[] = [1, 2, 3]
Output: 1
Explanation:
Binary tree of the given array:

Minimum-swap-required-to-convert-binary-tree-to-binary-search-tree-2

After swapping node 1 with node 2, obtain the below binary search tree:

Minimum-swap-required-to-convert-binary-tree-to-binary-search-tree-4
Try It Yourself
redirect icon

[Naive Approach] Try All Possible Swaps - O(n!) Time and O(n) Space

The idea is to first find the inorder traversal of the given tree.

We then create the target sorted order and recursively try all possible swaps to transform the current order into the target order.

To correctly handle duplicate values, each element is stored along with its original position, making every element uniquely identifiable.

Working of the Approach:

  • Perform an inorder traversal of the complete binary tree and store each element along with its original position.
  • Create a copy of the inorder traversal and sort it to obtain the target order.
  • Start from the first position and check whether the current element is already equal to the target element.
  • If it is not, try swapping it with every position containing the required target element.
  • Recursively solve the remaining positions after each swap.
  • Undo the swap after the recursive call so that other possible swaps can be tried.
  • Keep track of the minimum number of swaps among all possible choices.
  • Return the minimum number of swaps obtained.
C++
#include <bits/stdc++.h>
using namespace std;

int minSwapsRec(vector<pair<int, int>>& arr,
                vector<pair<int, int>>& target, int pos) {
    int n = arr.size();

    // Skip elements that are already in the correct position
    while (pos < n && arr[pos] == target[pos])
        pos++;

    if (pos == n)
        return 0;

    int ans = INT_MAX;

    // Try every possible swap for the current position
    for (int j = pos + 1; j < n; j++) {
        if (arr[j] == target[pos]) {
            swap(arr[pos], arr[j]);

            ans = min(ans,
                      1 + minSwapsRec(arr, target, pos + 1));

            swap(arr[pos], arr[j]);
        }
    }

    return ans;
}

void inorder(vector<int>& arr, int i,
             vector<pair<int, int>>& in) {
    if (i >= arr.size())
        return;

    inorder(arr, 2 * i + 1, in);

    in.push_back({arr[i], (int)in.size()});

    inorder(arr, 2 * i + 2, in);
}

int minSwaps(vector<int>& arr) {
    vector<pair<int, int>> in;

    inorder(arr, 0, in);

    vector<pair<int, int>> target = in;
    sort(target.begin(), target.end());

    return minSwapsRec(in, target, 0);
}

int main() {
    vector<int> arr = {5, 6, 7, 8, 9, 10, 11};

    cout << minSwaps(arr);

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

class GFG {

    static int minSwapsRec(List<int[]> arr,
                           List<int[]> target, int pos) {
        int n = arr.size();

        // Skip elements that are already in the correct position
        while (pos < n &&
               arr.get(pos)[0] == target.get(pos)[0] &&
               arr.get(pos)[1] == target.get(pos)[1]) {
            pos++;
        }

        if (pos == n)
            return 0;

        int ans = Integer.MAX_VALUE;

        // Try every possible swap for the current position
        for (int j = pos + 1; j < n; j++) {
            if (arr.get(j)[0] == target.get(pos)[0] &&
                arr.get(j)[1] == target.get(pos)[1]) {

                int[] temp = arr.get(pos);
                arr.set(pos, arr.get(j));
                arr.set(j, temp);

                ans = Math.min(ans,
                    1 + minSwapsRec(arr, target, pos + 1));

                temp = arr.get(pos);
                arr.set(pos, arr.get(j));
                arr.set(j, temp);
            }
        }

        return ans;
    }

    static void inorder(int[] arr, int i, List<int[]> in) {
        if (i >= arr.length)
            return;

        inorder(arr, 2 * i + 1, in);

        in.add(new int[]{arr[i], in.size()});

        inorder(arr, 2 * i + 2, in);
    }

    static int minSwaps(int[] arr) {
        List<int[]> in = new ArrayList<>();

        inorder(arr, 0, in);

        List<int[]> target = new ArrayList<>(in);

        target.sort(Comparator
            .comparingInt((int[] x) -> x[0])
            .thenComparingInt(x -> x[1]));

        return minSwapsRec(in, target, 0);
    }

    public static void main(String[] args) {
        int[] arr = {5, 6, 7, 8, 9, 10, 11};

        System.out.println(minSwaps(arr));
    }
}
Python
def minSwapsRec(arr, target, pos):
    n = len(arr)

    # Skip elements that are already in the correct position
    while pos < n and arr[pos] == target[pos]:
        pos += 1

    if pos == n:
        return 0

    ans = float('inf')

    # Try every possible swap for the current position
    for j in range(pos + 1, n):
        if arr[j] == target[pos]:
            arr[pos], arr[j] = arr[j], arr[pos]

            ans = min(ans,
                      1 + minSwapsRec(arr, target, pos + 1))

            arr[pos], arr[j] = arr[j], arr[pos]

    return ans


def inorder(arr, i, in_order):
    if i >= len(arr):
        return

    inorder(arr, 2 * i + 1, in_order)

    in_order.append((arr[i], len(in_order)))

    inorder(arr, 2 * i + 2, in_order)


def minSwaps(arr):
    in_order = []

    inorder(arr, 0, in_order)

    target = sorted(in_order)

    return minSwapsRec(in_order, target, 0)


if __name__ == "__main__":
    arr = [5, 6, 7, 8, 9, 10, 11]

    print(minSwaps(arr))
C#
using System;
using System.Collections.Generic;

class Item {
    public int value;
    public int index;

    public Item(int value, int index) {
        this.value = value;
        this.index = index;
    }
}

class GFG {

    static int minSwapsRec(List<Item> arr,
                           List<Item> target, int pos) {
        int n = arr.Count;

        // Skip elements that are already in the correct position
        while (pos < n &&
               arr[pos].value == target[pos].value &&
               arr[pos].index == target[pos].index) {
            pos++;
        }

        if (pos == n)
            return 0;

        int ans = int.MaxValue;

        // Try every possible swap for the current position
        for (int j = pos + 1; j < n; j++) {
            if (arr[j].value == target[pos].value &&
                arr[j].index == target[pos].index) {

                Item temp = arr[pos];
                arr[pos] = arr[j];
                arr[j] = temp;

                ans = Math.Min(ans,
                    1 + minSwapsRec(arr, target, pos + 1));

                temp = arr[pos];
                arr[pos] = arr[j];
                arr[j] = temp;
            }
        }

        return ans;
    }

    static void inorder(List<int> arr, int i, List<Item> inOrder) {
        if (i >= arr.Count)
            return;

        inorder(arr, 2 * i + 1, inOrder);

        inOrder.Add(new Item(arr[i], inOrder.Count));

        inorder(arr, 2 * i + 2, inOrder);
    }

    static int minSwaps(List<int> arr) {
        List<Item> inOrder = new List<Item>();

        inorder(arr, 0, inOrder);

        List<Item> target = new List<Item>(inOrder);

        target.Sort((a, b) => {
            if (a.value != b.value)
                return a.value.CompareTo(b.value);

            return a.index.CompareTo(b.index);
        });

        return minSwapsRec(inOrder, target, 0);
    }

    static void Main() {
        List<int> arr = new List<int> { 5, 6, 7, 8, 9, 10, 11 };

        Console.WriteLine(minSwaps(arr));
    }
}
JavaScript
function minSwapsRec(arr, target, pos) {
    let n = arr.length;

    // Skip elements that are already in the correct position
    while (pos < n &&
           arr[pos].value === target[pos].value &&
           arr[pos].index === target[pos].index) {
        pos++;
    }

    if (pos === n)
        return 0;

    let ans = Infinity;

    // Try every possible swap for the current position
    for (let j = pos + 1; j < n; j++) {
        if (arr[j].value === target[pos].value &&
            arr[j].index === target[pos].index) {

            [arr[pos], arr[j]] = [arr[j], arr[pos]];

            ans = Math.min(
                ans,
                1 + minSwapsRec(arr, target, pos + 1)
            );

            [arr[pos], arr[j]] = [arr[j], arr[pos]];
        }
    }

    return ans;
}

function inorder(arr, i, inOrder) {
    if (i >= arr.length)
        return;

    inorder(arr, 2 * i + 1, inOrder);

    inOrder.push({
        value: arr[i],
        index: inOrder.length
    });

    inorder(arr, 2 * i + 2, inOrder);
}

function minSwaps(arr) {
    let inOrder = [];

    inorder(arr, 0, inOrder);

    let target = [...inOrder];

    target.sort((a, b) => {
        if (a.value !== b.value)
            return a.value - b.value;

        return a.index - b.index;
    });

    return minSwapsRec(inOrder, target, 0);
}

// Driver Code
let arr = [5, 6, 7, 8, 9, 10, 11];

console.log(minSwaps(arr));

Output
3

[Expected Approach] Inorder Traversal + Cycle Decomposition - O(n log n) Time and O(n) Space

First find the inorder traversal of the given complete binary tree and create its sorted version.

The current inorder array can be viewed as a permutation of the sorted array. By finding cycles in this permutation, we can calculate the minimum number of swaps required.

A cycle containing k elements requires exactly k - 1 swaps.

Working of the Approach:

  • Perform an inorder traversal of the complete binary tree and store each element along with its original position.
  • Create a copy of the inorder traversal and sort it to obtain the target sorted order.
  • Map each element of the current inorder array to its corresponding position in the sorted array.
  • Traverse this mapping and identify cycles of elements that need to be rearranged.
  • For every cycle of length k, add k - 1 to the swap count.
  • Treat duplicate values using their original positions so that each element has a unique identity.
  • Return the total number of swaps as the minimum number required to convert the complete binary tree into a BST.
C++
#include <bits/stdc++.h>
using namespace std;

void inorder(vector<int>& arr, int i, vector<pair<int, int>>& in) {
    if (i >= arr.size())
        return;

    inorder(arr, 2 * i + 1, in);
    in.push_back({arr[i], (int)in.size()});
    inorder(arr, 2 * i + 2, in);
}

int minSwaps(vector<int>& arr) {
    vector<pair<int, int>> in;
    inorder(arr, 0, in);

    int n = in.size();
    vector<pair<int, int>> target = in;
    sort(target.begin(), target.end());

    unordered_map<long long, int> pos;

    // Store the target position of every element
    for (int i = 0; i < n; i++) {
        long long key = (long long)target[i].first * 1000000
                        + target[i].second;
        pos[key] = i;
    }

    vector<bool> visited(n, false);
    int swaps = 0;

    // Count swaps using cycle decomposition
    for (int i = 0; i < n; i++) {
        if (visited[i])
            continue;

        int j = i;
        int cycleSize = 0;

        while (!visited[j]) {
            visited[j] = true;

            long long key = (long long)in[j].first * 1000000
                            + in[j].second;

            j = pos[key];
            cycleSize++;
        }

        if (cycleSize > 1)
            swaps += cycleSize - 1;
    }

    return swaps;
}

int main() {
    vector<int> arr = {5, 6, 7, 8, 9, 10, 11};

    cout << minSwaps(arr);

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class GFG {

    static void inorder(int[] arr, int i, List<int[]> in) {
        if (i >= arr.length)
            return;

        inorder(arr, 2 * i + 1, in);
        in.add(new int[]{arr[i], in.size()});
        inorder(arr, 2 * i + 2, in);
    }

    static int minSwaps(int[] arr) {
        List<int[]> in = new ArrayList<>();
        inorder(arr, 0, in);

        int n = in.size();
        List<int[]> target = new ArrayList<>(in);

        // Sort the inorder traversal to get target order
        target.sort((a, b) -> {
            if (a[0] != b[0])
                return Integer.compare(a[0], b[0]);

            return Integer.compare(a[1], b[1]);
        });

        Map<String, Integer> pos = new HashMap<>();

        // Store the target position of every element
        for (int i = 0; i < n; i++)
            pos.put(target.get(i)[0] + "#" + target.get(i)[1], i);

        boolean[] visited = new boolean[n];
        int swaps = 0;

        // Count swaps using cycle decomposition
        for (int i = 0; i < n; i++) {
            if (visited[i])
                continue;

            int j = i;
            int cycleSize = 0;

            while (!visited[j]) {
                visited[j] = true;

                int[] element = in.get(j);
                j = pos.get(element[0] + "#" + element[1]);
                cycleSize++;
            }

            if (cycleSize > 1)
                swaps += cycleSize - 1;
        }

        return swaps;
    }

    public static void main(String[] args) {
        int[] arr = {5, 6, 7, 8, 9, 10, 11};

        System.out.println(minSwaps(arr));
    }
}
Python
def inorder(arr, i, in_order):
    if i >= len(arr):
        return

    inorder(arr, 2 * i + 1, in_order)
    in_order.append((arr[i], len(in_order)))
    inorder(arr, 2 * i + 2, in_order)


def minSwaps(arr):
    in_order = []
    inorder(arr, 0, in_order)

    n = len(in_order)
    target = sorted(in_order)

    # Store the target position of every element
    pos = {element: i for i, element in enumerate(target)}

    visited = [False] * n
    swaps = 0

    # Count swaps using cycle decomposition
    for i in range(n):
        if visited[i]:
            continue

        j = i
        cycle_size = 0

        while not visited[j]:
            visited[j] = True
            j = pos[in_order[j]]
            cycle_size += 1

        if cycle_size > 1:
            swaps += cycle_size - 1

    return swaps


if __name__ == "__main__":
    arr = [5, 6, 7, 8, 9, 10, 11]

    print(minSwaps(arr))
C#
using System;
using System.Collections.Generic;

class GFG {

    static void inorder(List<int> arr, int i,
                        List<(int value, int index)> inOrder) {
        if (i >= arr.Count)
            return;

        inorder(arr, 2 * i + 1, inOrder);
        inOrder.Add((arr[i], inOrder.Count));
        inorder(arr, 2 * i + 2, inOrder);
    }

    static int minSwaps(List<int> arr) {
        List<(int value, int index)> inOrder =
            new List<(int value, int index)>();

        inorder(arr, 0, inOrder);

        int n = inOrder.Count;
        List<(int value, int index)> target =
            new List<(int value, int index)>(inOrder);

        // Sort the inorder traversal to get target order
        target.Sort((a, b) => {
            if (a.value != b.value)
                return a.value.CompareTo(b.value);

            return a.index.CompareTo(b.index);
        });

        Dictionary<(int value, int index), int> pos =
            new Dictionary<(int value, int index), int>();

        // Store the target position of every element
        for (int i = 0; i < n; i++)
            pos[target[i]] = i;

        bool[] visited = new bool[n];
        int swaps = 0;

        // Count swaps using cycle decomposition
        for (int i = 0; i < n; i++) {
            if (visited[i])
                continue;

            int j = i;
            int cycleSize = 0;

            while (!visited[j]) {
                visited[j] = true;
                j = pos[inOrder[j]];
                cycleSize++;
            }

            if (cycleSize > 1)
                swaps += cycleSize - 1;
        }

        return swaps;
    }

    static void Main() {
        List<int> arr = new List<int> { 5, 6, 7, 8, 9, 10, 11 };

        Console.WriteLine(minSwaps(arr));
    }
}
JavaScript
function inorder(arr, i, inOrder) {
    if (i >= arr.length)
        return;

    inorder(arr, 2 * i + 1, inOrder);
    inOrder.push([arr[i], inOrder.length]);
    inorder(arr, 2 * i + 2, inOrder);
}

function minSwaps(arr) {
    let inOrder = [];
    inorder(arr, 0, inOrder);

    let n = inOrder.length;
    let target = [...inOrder];

    // Sort the inorder traversal to get target order
    target.sort((a, b) => {
        if (a[0] !== b[0])
            return a[0] - b[0];

        return a[1] - b[1];
    });

    let pos = new Map();

    // Store the target position of every element
    for (let i = 0; i < n; i++)
        pos.set(target[i][0] + "#" + target[i][1], i);

    let visited = new Array(n).fill(false);
    let swaps = 0;

    // Count swaps using cycle decomposition
    for (let i = 0; i < n; i++) {
        if (visited[i])
            continue;

        let j = i;
        let cycleSize = 0;

        while (!visited[j]) {
            visited[j] = true;

            let element = inOrder[j];
            j = pos.get(element[0] + "#" + element[1]);
            cycleSize++;
        }

        if (cycleSize > 1)
            swaps += cycleSize - 1;
    }

    return swaps;
}

// Driver Code
let arr = [5, 6, 7, 8, 9, 10, 11];

console.log(minSwaps(arr));

Output
3
Comment