Open In App

Minimum swaps to sort the leaf nodes in a Perfect Binary Tree

Last Updated : 09 Dec, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Given a perfect binary tree of height N  and an array of length 2N which represents the values of leaf nodes from left to right. An operation is defined as choosing any non-leaf vertex of the tree and swapping its left and right sons (along with their subtrees). Find the minimum number of such operations required to sort the value of leaf nodes in increasing order.

Examples:

Input: N = 3, leaf[] = {4, 3, 2, 1, 5, 6, 7, 8}

Tree representing given input

Output: 3
Explanation: Swap the left and right part of subtree having leaf nodes 4 and 3, swap left and right part of subtree having leaf nodes 2 and 1 and finally swap left and right part of whole left subtree of root having leaf nodes as 4, 3, 2, 1. Total swap operations performed is equal to three which is minimum to sort the leaf nodes in increasing order.

Input: N=2, leaf[] = {3, 1, 4, 2}

Tree representing given input

Output: -1
Explanation: We can perform two swapping operations on left and right part of subtrees having leaf nodes as 3&1 and 4&2, but we will get the leaf nodes in order {1, 3, 2, 4} which isn’t sorted. Since the leaf nodes are not sorted in increasing order so we return -1.

Approach: To solve the problem follow the below idea:

The idea/intuition is to use the divide and conquer technique, we recursively call our function for the left and right half of the tree to give the operations required to sort the leaf nodes in the left and right subtree. At last, we check if the array is sorted so we return the minimum operations otherwise if the array isn’t sorted we return -1.

Follow the steps to solve the problem:

  • Initialize two pointers low = 0 and high = n – 1 and make the initial call to calculate swaps for sorting leaf nodes and result = 0.
  • Find the mid pointer, mid = low + (high – low) / 2.
  • Call minSwapsFunction recursively for the left subtree containing leaf nodes from 0 to mid and the right subtree containing leaf nodes from mid + 1 to high.
    • Merge the left and right subtree of the non-leaf vertex, check and perform the swap if the leaf nodes in the right part are lesser than the leaf nodes in the left part, and increment the result as you swap.
  • In the end, check if the leaf nodes are sorted or not, and return the result if they are sorted otherwise return -1.

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to perform swap in the left
// and right parts if required
bool mergeSubTrees(vector<int>& a, int low, int mid,
                   int high)
{
    // If the leaf nodes are already sorted
    if (a[mid] < a[mid + 1])
        return 0;
 
    // Swapping the left leaf nodes
    // with right leafnodes
    for (int i = low; i <= mid; i++)
        swap(a[i], a[i + (high - low + 1) / 2]);
    return 1;
}
 
// Recursive function to count the
// operations required in left and right
// subtree to make leaf nodes sorted
void minSwapsRequired(vector<int>& a, int low, int high,
                      int& result)
{
    if (low < high) {
 
        // Calculating middle point for
        // partitioning the tree into
        // left and right subtrees
        int mid = low + (high - low) / 2;
 
        // Recursive call for left subtree
        minSwapsRequired(a, low, mid, result);
 
        // Recursive call for right subtree
        minSwapsRequired(a, mid + 1, high, result);
 
        // If swap was made in left
        // and right part of subtrees
        // then increase the result
        if (mergeSubTrees(a, low, mid, high))
            result++;
    }
}
 
// Driver code
int main()
{
    int N = 3;
 
    // Perfect tree with N height
    // has 2^N leaf nodes
    N = (1 << N);
    vector<int> a = { 4, 3, 2, 1, 5, 6, 7, 8 };
 
    int result = 0;
 
    minSwapsRequired(a, 0, N - 1, result);
 
    // Check if the leaf nodes are
    // now in increasing order or not
    if (is_sorted(a.begin(), a.end()))
        cout << result;
    else
        cout << -1;
 
    return 0;
}


Java




/*package whatever //do not write package name here */
 
import java.io.*;
import java.util.*;
 
class GFG {
 
  public static ArrayList<Integer> a
    = new ArrayList<Integer>();
  public static int result = 0;
 
  public static boolean is_sorted(ArrayList<Integer> a)
  {
    for (int i = 1; i < a.size(); i++) {
      if (a.get(i) < a.get(i - 1))
        return false;
    }
 
    return true;
  }
 
  // Function to perform swap in the left
  // and right parts if required
  public static boolean
    mergeSubTrees(ArrayList<Integer> a, int low, int mid,
                  int high)
  {
    // If the leaf nodes are already sorted
    if (a.get(mid) < a.get(mid + 1)) {
      return false;
    }
 
    // Swapping the left leaf nodes
    // with right leafnodes
    for (int i = low; i <= mid; i++) {
      int tempswap = a.get(i);
      a.set(i, a.get(i + (high - low + 1) / 2));
      a.set(i + (high - low + 1) / 2, tempswap);
    }
    return true;
  }
 
  // Recursive function to count the
  // operations required in left and right
  // subtree to make leaf nodes sorted
  public static void
    minSwapsRequired(ArrayList<Integer> a, int low,
                     int high)
  {
    if (low < high) {
 
      // Calculating middle point for
      // partitioning the tree into
      // left and right subtrees
      int mid = low + (high - low) / 2;
 
      // Recursive call for left subtree
      minSwapsRequired(a, low, mid);
 
      // Recursive call for right subtree
      minSwapsRequired(a, mid + 1, high);
 
      // If swap was made in left
      // and right part of subtrees
      // then increase the result
      if (mergeSubTrees(a, low, mid, high) == true) {
        result = result + 1;
      }
    }
  }
 
  public static void main(String[] args)
  {
    int N = 3;
 
    // Perfect tree with N height
    // has 2^N leaf nodes
    N = (1 << N);
    a.add(4);
    a.add(3);
    a.add(2);
    a.add(1);
    a.add(5);
    a.add(6);
    a.add(7);
    a.add(8);
 
    minSwapsRequired(a, 0, N - 1);
 
    // Check if the leaf nodes are
    // now in increasing order or not
    if (is_sorted(a))
      System.out.println(result);
    else
      System.out.println("-1");
  }
}
 
// This code is contributed by akashish__


Python3




# Python code for the above approach
result = 0;
 
# Function to perform swap in the left
# and right parts if required
def mergeSubTrees(a, low, mid, high):
     
    # If the leaf nodes are already sorted
    if (a[mid] < a[mid + 1]):
        return 0;
 
    # Swapping the left leaf nodes
    # with right leafnodes
    for i in range(low, mid + 1):
        temp = a[i];
        a[i] = a[i + (high - low + 1) // 2];
        a[i + (high - low + 1) // 2] = temp;
     
    return 1;
 
 
# Recursive function to count the
# operations required in left and right
# subtree to make leaf nodes sorted
def minSwapsRequired(a, low, high):
    global result;
    if (low < high):
 
        # Calculating middle point for
        # partitioning the tree into
        # left and right subtrees
        mid = (high + low) // 2;
 
        # Recursive call for left subtree
        minSwapsRequired(a, low, mid);
 
        # Recursive call for right subtree
        minSwapsRequired(a, mid + 1, high);
 
        # If swap was made in left
        # and right part of subtrees
        # then increase the result
        if (mergeSubTrees(a, low, mid, high)):
            result += 1
 
 
def is_sorted(a):
    for i in range(1, len(a)):
        if (a[i] < a[i - 1]):
            return 0;
 
    return 1;
 
 
# Driver code
N = 3;
 
# Perfect tree with N height
# has 2^N leaf nodes
N = (1 << N);
a = [4, 3, 2, 1, 5, 6, 7, 8];
 
minSwapsRequired(a, 0, N - 1);
 
# Check if the leaf nodes are
# now in increasing order or not
if (is_sorted(a)):
    print(result);
else:
    print(-1);
 
 # This code is contributed by Saurabh Jaiswal


C#




// C# code to implement the approach
using System;
public class GFG {
 
  public static bool is_sorted(int[] a)
  {
    for (int i = 1; i < a.Length; i++) {
      if (a[i] < a[i - 1])
        return false;
    }
 
    return true;
  }
 
  static void swap(ref int x, ref int y)
  {
    int tempswap = x;
    x = y;
    y = tempswap;
  }
 
  // Function to perform swap in the left
  // and right parts if required
  public static bool mergeSubTrees(ref int[] a, int low,
                                   int mid, int high)
  {
    // If the leaf nodes are already sorted
    if (a[mid] < a[mid + 1])
      return false;
 
    // Swapping the left leaf nodes
    // with right leafnodes
    for (int i = low; i <= mid; i++)
      swap(ref a[i], ref a[i + (high - low + 1) / 2]);
    return true;
  }
 
  // Recursive function to count the
  // operations required in left and right
  // subtree to make leaf nodes sorted
  public static void minSwapsRequired(ref int[] a,
                                      int low, int high,
                                      ref int result)
  {
    if (low < high) {
 
      // Calculating middle point for
      // partitioning the tree into
      // left and right subtrees
      int mid = low + (high - low) / 2;
 
      // Recursive call for left subtree
      minSwapsRequired(ref a, low, mid, ref result);
 
      // Recursive call for right subtree
      minSwapsRequired(ref a, mid + 1, high,
                       ref result);
 
      // If swap was made in left
      // and right part of subtrees
      // then increase the result
      if (mergeSubTrees(ref a, low, mid, high))
        result++;
    }
  }
 
  // Driver code
  static public void Main()
  {
 
    int N = 3;
 
    // Perfect tree with N height
    // has 2^N leaf nodes
    N = (1 << N);
    int[] a = { 4, 3, 2, 1, 5, 6, 7, 8 };
 
    int result = 0;
 
    minSwapsRequired(ref a, 0, N - 1, ref result);
 
    // Check if the leaf nodes are
    // now in increasing order or not
    if (is_sorted(a))
      Console.WriteLine(result);
    else
      Console.WriteLine(-1);
  }
}
 
// This code is contributed by akashish__


Javascript




<script>
        // JavaScript code for the above approach
        var result = 0;
         
        // Function to perform swap in the left
        // and right parts if required
        function mergeSubTrees(a, low, mid,
            high)
            {
             
            // If the leaf nodes are already sorted
            if (a[mid] < a[mid + 1])
                return 0;
 
            // Swapping the left leaf nodes
            // with right leafnodes
            for (let i = low; i <= mid; i++) {
                let temp = a[i];
                a[i] = a[i + Math.floor((high - low + 1) / 2)];
                a[i + Math.floor((high - low + 1) / 2)] = temp;
            }
            return 1;
        }
 
        // Recursive function to count the
        // operations required in left and right
        // subtree to make leaf nodes sorted
        function minSwapsRequired(a, low, high
        ) {
            if (low < high) {
 
                // Calculating middle point for
                // partitioning the tree into
                // left and right subtrees
                let mid = Math.floor((high + low) / 2);
 
                // Recursive call for left subtree
                minSwapsRequired(a, low, mid);
 
                // Recursive call for right subtree
                minSwapsRequired(a, mid + 1, high);
 
                // If swap was made in left
                // and right part of subtrees
                // then increase the result
                if (mergeSubTrees(a, low, mid, high))
                    result++;
            }
        }
 
        function is_sorted(a) {
            for (let i = 1; i < a.length; i++) {
                if (a[i] < a[i - 1])
                    return 0;
            }
 
            return 1;
        }
         
        // Driver code
        let N = 3;
 
        // Perfect tree with N height
        // has 2^N leaf nodes
        N = (1 << N);
        var a = [4, 3, 2, 1, 5, 6, 7, 8];
 
        minSwapsRequired(a, 0, N - 1, result);
         
        // Check if the leaf nodes are
        // now in increasing order or not
        if (is_sorted(a))
            document.write(result);
        else
            document.write(-1);
 
 // This code is contributed by Potta Lokesh
 
    </script>


Output

3

Time Complexity: O(N * log N)
Auxiliary Space: O(N), recursion stack space



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads