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:
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:
Input: arr[] = [1, 2, 3] Output: 1 Explanation: Binary tree of the given array:
After swapping node 1 with node 2, obtain the below binary search tree:
[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>usingnamespacestd;intminSwapsRec(vector<pair<int,int>>&arr,vector<pair<int,int>>&target,intpos){intn=arr.size();// Skip elements that are already in the correct positionwhile(pos<n&&arr[pos]==target[pos])pos++;if(pos==n)return0;intans=INT_MAX;// Try every possible swap for the current positionfor(intj=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]);}}returnans;}voidinorder(vector<int>&arr,inti,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);}intminSwaps(vector<int>&arr){vector<pair<int,int>>in;inorder(arr,0,in);vector<pair<int,int>>target=in;sort(target.begin(),target.end());returnminSwapsRec(in,target,0);}intmain(){vector<int>arr={5,6,7,8,9,10,11};cout<<minSwaps(arr);return0;}
Java
importjava.util.ArrayList;importjava.util.Comparator;importjava.util.List;classGFG{staticintminSwapsRec(List<int[]>arr,List<int[]>target,intpos){intn=arr.size();// Skip elements that are already in the correct positionwhile(pos<n&&arr.get(pos)[0]==target.get(pos)[0]&&arr.get(pos)[1]==target.get(pos)[1]){pos++;}if(pos==n)return0;intans=Integer.MAX_VALUE;// Try every possible swap for the current positionfor(intj=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);}}returnans;}staticvoidinorder(int[]arr,inti,List<int[]>in){if(i>=arr.length)return;inorder(arr,2*i+1,in);in.add(newint[]{arr[i],in.size()});inorder(arr,2*i+2,in);}staticintminSwaps(int[]arr){List<int[]>in=newArrayList<>();inorder(arr,0,in);List<int[]>target=newArrayList<>(in);target.sort(Comparator.comparingInt((int[]x)->x[0]).thenComparingInt(x->x[1]));returnminSwapsRec(in,target,0);}publicstaticvoidmain(String[]args){int[]arr={5,6,7,8,9,10,11};System.out.println(minSwaps(arr));}}
Python
defminSwapsRec(arr,target,pos):n=len(arr)# Skip elements that are already in the correct positionwhilepos<nandarr[pos]==target[pos]:pos+=1ifpos==n:return0ans=float('inf')# Try every possible swap for the current positionforjinrange(pos+1,n):ifarr[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]returnansdefinorder(arr,i,in_order):ifi>=len(arr):returninorder(arr,2*i+1,in_order)in_order.append((arr[i],len(in_order)))inorder(arr,2*i+2,in_order)defminSwaps(arr):in_order=[]inorder(arr,0,in_order)target=sorted(in_order)returnminSwapsRec(in_order,target,0)if__name__=="__main__":arr=[5,6,7,8,9,10,11]print(minSwaps(arr))
C#
usingSystem;usingSystem.Collections.Generic;classItem{publicintvalue;publicintindex;publicItem(intvalue,intindex){this.value=value;this.index=index;}}classGFG{staticintminSwapsRec(List<Item>arr,List<Item>target,intpos){intn=arr.Count;// Skip elements that are already in the correct positionwhile(pos<n&&arr[pos].value==target[pos].value&&arr[pos].index==target[pos].index){pos++;}if(pos==n)return0;intans=int.MaxValue;// Try every possible swap for the current positionfor(intj=pos+1;j<n;j++){if(arr[j].value==target[pos].value&&arr[j].index==target[pos].index){Itemtemp=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;}}returnans;}staticvoidinorder(List<int>arr,inti,List<Item>inOrder){if(i>=arr.Count)return;inorder(arr,2*i+1,inOrder);inOrder.Add(newItem(arr[i],inOrder.Count));inorder(arr,2*i+2,inOrder);}staticintminSwaps(List<int>arr){List<Item>inOrder=newList<Item>();inorder(arr,0,inOrder);List<Item>target=newList<Item>(inOrder);target.Sort((a,b)=>{if(a.value!=b.value)returna.value.CompareTo(b.value);returna.index.CompareTo(b.index);});returnminSwapsRec(inOrder,target,0);}staticvoidMain(){List<int>arr=newList<int>{5,6,7,8,9,10,11};Console.WriteLine(minSwaps(arr));}}
JavaScript
functionminSwapsRec(arr,target,pos){letn=arr.length;// Skip elements that are already in the correct positionwhile(pos<n&&arr[pos].value===target[pos].value&&arr[pos].index===target[pos].index){pos++;}if(pos===n)return0;letans=Infinity;// Try every possible swap for the current positionfor(letj=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]];}}returnans;}functioninorder(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);}functionminSwaps(arr){letinOrder=[];inorder(arr,0,inOrder);lettarget=[...inOrder];target.sort((a,b)=>{if(a.value!==b.value)returna.value-b.value;returna.index-b.index;});returnminSwapsRec(inOrder,target,0);}// Driver Codeletarr=[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>usingnamespacestd;voidinorder(vector<int>&arr,inti,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);}intminSwaps(vector<int>&arr){vector<pair<int,int>>in;inorder(arr,0,in);intn=in.size();vector<pair<int,int>>target=in;sort(target.begin(),target.end());unordered_map<longlong,int>pos;// Store the target position of every elementfor(inti=0;i<n;i++){longlongkey=(longlong)target[i].first*1000000+target[i].second;pos[key]=i;}vector<bool>visited(n,false);intswaps=0;// Count swaps using cycle decompositionfor(inti=0;i<n;i++){if(visited[i])continue;intj=i;intcycleSize=0;while(!visited[j]){visited[j]=true;longlongkey=(longlong)in[j].first*1000000+in[j].second;j=pos[key];cycleSize++;}if(cycleSize>1)swaps+=cycleSize-1;}returnswaps;}intmain(){vector<int>arr={5,6,7,8,9,10,11};cout<<minSwaps(arr);return0;}
Java
importjava.util.ArrayList;importjava.util.Arrays;importjava.util.HashMap;importjava.util.List;importjava.util.Map;classGFG{staticvoidinorder(int[]arr,inti,List<int[]>in){if(i>=arr.length)return;inorder(arr,2*i+1,in);in.add(newint[]{arr[i],in.size()});inorder(arr,2*i+2,in);}staticintminSwaps(int[]arr){List<int[]>in=newArrayList<>();inorder(arr,0,in);intn=in.size();List<int[]>target=newArrayList<>(in);// Sort the inorder traversal to get target ordertarget.sort((a,b)->{if(a[0]!=b[0])returnInteger.compare(a[0],b[0]);returnInteger.compare(a[1],b[1]);});Map<String,Integer>pos=newHashMap<>();// Store the target position of every elementfor(inti=0;i<n;i++)pos.put(target.get(i)[0]+"#"+target.get(i)[1],i);boolean[]visited=newboolean[n];intswaps=0;// Count swaps using cycle decompositionfor(inti=0;i<n;i++){if(visited[i])continue;intj=i;intcycleSize=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;}returnswaps;}publicstaticvoidmain(String[]args){int[]arr={5,6,7,8,9,10,11};System.out.println(minSwaps(arr));}}
Python
definorder(arr,i,in_order):ifi>=len(arr):returninorder(arr,2*i+1,in_order)in_order.append((arr[i],len(in_order)))inorder(arr,2*i+2,in_order)defminSwaps(arr):in_order=[]inorder(arr,0,in_order)n=len(in_order)target=sorted(in_order)# Store the target position of every elementpos={element:ifori,elementinenumerate(target)}visited=[False]*nswaps=0# Count swaps using cycle decompositionforiinrange(n):ifvisited[i]:continuej=icycle_size=0whilenotvisited[j]:visited[j]=Truej=pos[in_order[j]]cycle_size+=1ifcycle_size>1:swaps+=cycle_size-1returnswapsif__name__=="__main__":arr=[5,6,7,8,9,10,11]print(minSwaps(arr))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{staticvoidinorder(List<int>arr,inti,List<(intvalue,intindex)>inOrder){if(i>=arr.Count)return;inorder(arr,2*i+1,inOrder);inOrder.Add((arr[i],inOrder.Count));inorder(arr,2*i+2,inOrder);}staticintminSwaps(List<int>arr){List<(intvalue,intindex)>inOrder=newList<(intvalue,intindex)>();inorder(arr,0,inOrder);intn=inOrder.Count;List<(intvalue,intindex)>target=newList<(intvalue,intindex)>(inOrder);// Sort the inorder traversal to get target ordertarget.Sort((a,b)=>{if(a.value!=b.value)returna.value.CompareTo(b.value);returna.index.CompareTo(b.index);});Dictionary<(intvalue,intindex),int>pos=newDictionary<(intvalue,intindex),int>();// Store the target position of every elementfor(inti=0;i<n;i++)pos[target[i]]=i;bool[]visited=newbool[n];intswaps=0;// Count swaps using cycle decompositionfor(inti=0;i<n;i++){if(visited[i])continue;intj=i;intcycleSize=0;while(!visited[j]){visited[j]=true;j=pos[inOrder[j]];cycleSize++;}if(cycleSize>1)swaps+=cycleSize-1;}returnswaps;}staticvoidMain(){List<int>arr=newList<int>{5,6,7,8,9,10,11};Console.WriteLine(minSwaps(arr));}}
JavaScript
functioninorder(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);}functionminSwaps(arr){letinOrder=[];inorder(arr,0,inOrder);letn=inOrder.length;lettarget=[...inOrder];// Sort the inorder traversal to get target ordertarget.sort((a,b)=>{if(a[0]!==b[0])returna[0]-b[0];returna[1]-b[1];});letpos=newMap();// Store the target position of every elementfor(leti=0;i<n;i++)pos.set(target[i][0]+"#"+target[i][1],i);letvisited=newArray(n).fill(false);letswaps=0;// Count swaps using cycle decompositionfor(leti=0;i<n;i++){if(visited[i])continue;letj=i;letcycleSize=0;while(!visited[j]){visited[j]=true;letelement=inOrder[j];j=pos.get(element[0]+"#"+element[1]);cycleSize++;}if(cycleSize>1)swaps+=cycleSize-1;}returnswaps;}// Driver Codeletarr=[5,6,7,8,9,10,11];console.log(minSwaps(arr));