Open In App

Number of swaps to sort when only adjacent swapping allowed

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of non negative integers. We can perform a swap operation on any two adjacent elements in the array. Find the minimum number of swaps needed to sort the array in ascending order. 

Examples : 

Input  : arr[] = {3, 2, 1}
Output : 3
We need to do following swaps (3, 2), (3, 1) and (1, 2)

Input  : arr[] = {1, 20, 6, 4, 5}
Output : 5

There is an interesting solution to this problem. It can be solved using the fact that a number of swaps needed is equal to number of inversions. So we basically need to count inversions in array.

The fact can be established using below observations: 

  1. A sorted array has no inversions. 
  2. An adjacent swap can reduce one inversion. Doing x adjacent swaps can reduce x inversions in an array. 

Implementation:

C++




// C++ program to count number of swaps required
// to sort an array when only swapping of adjacent
// elements is allowed.
#include <bits/stdc++.h>
 
/* This function merges two sorted arrays and returns inversion
   count in the arrays.*/
int merge(int arr[], int temp[], int left, int mid, int right)
{
    int inv_count = 0;
 
    int i = left; /* i is index for left subarray*/
    int j = mid;  /* j is index for right subarray*/
    int k = left; /* k is index for resultant merged subarray*/
    while ((i <= mid - 1) && (j <= right))
    {
        if (arr[i] <= arr[j])
            temp[k++] = arr[i++];
        else
        {
            temp[k++] = arr[j++];
 
            /* this is tricky -- see above explanation/
              diagram for merge()*/
            inv_count = inv_count + (mid - i);
        }
    }
 
    /* Copy the remaining elements of left subarray
     (if there are any) to temp*/
    while (i <= mid - 1)
        temp[k++] = arr[i++];
 
    /* Copy the remaining elements of right subarray
     (if there are any) to temp*/
    while (j <= right)
        temp[k++] = arr[j++];
 
    /*Copy back the merged elements to original array*/
    for (i=left; i <= right; i++)
        arr[i] = temp[i];
 
    return inv_count;
}
 
/* An auxiliary recursive function that sorts the input
   array and returns the number of inversions in the
   array. */
int _mergeSort(int arr[], int temp[], int left, int right)
{
    int mid, inv_count = 0;
    if (right > left)
    {
        /* Divide the array into two parts and call
          _mergeSortAndCountInv() for each of the parts */
        mid = (right + left)/2;
 
        /* Inversion count will be sum of inversions in
           left-part, right-part and number of inversions
           in merging */
        inv_count  = _mergeSort(arr, temp, left, mid);
        inv_count += _mergeSort(arr, temp, mid+1, right);
 
        /*Merge the two parts*/
        inv_count += merge(arr, temp, left, mid+1, right);
    }
 
    return inv_count;
}
 
/* This function sorts the input array and returns the
   number of inversions in the array */
int countSwaps(int arr[], int n)
{
    int temp[n];
    return _mergeSort(arr, temp, 0, n - 1);
}
 
/* Driver program to test above functions */
int main(int argv, char** args)
{
    int arr[] = {1, 20, 6, 4, 5};
    int n = sizeof(arr)/sizeof(arr[0]);
    printf("Number of swaps is %d \n", countSwaps(arr, n));
    return 0;
}


Java




// Java program to count number of
// swaps required to sort an array
// when only swapping of adjacent
// elements is allowed.
import java.io.*;
 
class GFG {
     
// This function merges two sorted
// arrays and returns inversion
// count in the arrays.
static int merge(int arr[], int temp[],
            int left, int mid, int right)
{
    int inv_count = 0;
 
    /* i is index for left subarray*/
    int i = left;
     
    /* j is index for right subarray*/
    int j = mid;
     
    /* k is index for resultant merged subarray*/
    int k = left;
     
    while ((i <= mid - 1) && (j <= right))
    {
        if (arr[i] <= arr[j])
            temp[k++] = arr[i++];
        else
        {
            temp[k++] = arr[j++];
 
            /* this is tricky -- see above /
             explanation diagram for merge()*/
            inv_count = inv_count + (mid - i);
        }
    }
 
    /* Copy the remaining elements of left
    subarray (if there are any) to temp*/
    while (i <= mid - 1)
        temp[k++] = arr[i++];
 
    /* Copy the remaining elements of right
    subarray (if there are any) to temp*/
    while (j <= right)
        temp[k++] = arr[j++];
 
    /*Copy back the merged elements
    to original array*/
    for (i=left; i <= right; i++)
        arr[i] = temp[i];
 
    return inv_count;
}
 
// An auxiliary recursive function that
// sorts the input array and returns
// the number of inversions in the array.
static int _mergeSort(int arr[], int temp[],
                         int left, int right)
{
    int mid, inv_count = 0;
    if (right > left)
    {
        // Divide the array into two parts and
        // call _mergeSortAndCountInv() for
        // each of the parts
        mid = (right + left)/2;
 
        /* Inversion count will be sum of
        inversions in left-part, right-part
        and number of inversions in merging */
        inv_count = _mergeSort(arr, temp,
                                left, mid);
                                 
        inv_count += _mergeSort(arr, temp,
                                mid+1, right);
 
        /*Merge the two parts*/
        inv_count += merge(arr, temp,
                        left, mid+1, right);
    }
 
    return inv_count;
}
 
// This function sorts the input
// array and returns the number
// of inversions in the array
static int countSwaps(int arr[], int n)
{
    int temp[] = new int[n];
    return _mergeSort(arr, temp, 0, n - 1);
}
 
// Driver Code
public static void main (String[] args)
{
 
    int arr[] = {1, 20, 6, 4, 5};
    int n = arr.length;
        System.out.println("Number of swaps is "
                           + countSwaps(arr, n));
    }
}
 
// This code is contributed by vt_m


Python3




# python 3 program to count number of swaps required
# to sort an array when only swapping of adjacent
# elements is allowed.
#include <bits/stdc++.h>
 
#This function merges two sorted arrays and returns inversion count in the arrays.*/
def merge(arr, temp, left, mid, right):
    inv_count = 0
 
    i = left #i is index for left subarray*/
    j = mid #j is index for right subarray*/
    k = left #k is index for resultant merged subarray*/
    while ((i <= mid - 1) and (j <= right)):
        if (arr[i] <= arr[j]):
            temp[k] = arr[i]
            k += 1
            i += 1
        else:
            temp[k] = arr[j]
            k += 1
            j += 1
 
            #this is tricky -- see above explanation/
            # diagram for merge()*/
            inv_count = inv_count + (mid - i)
 
    #Copy the remaining elements of left subarray
    # (if there are any) to temp*/
    while (i <= mid - 1):
        temp[k] = arr[i]
        k += 1
        i += 1
 
    #Copy the remaining elements of right subarray
    # (if there are any) to temp*/
    while (j <= right):
        temp[k] = arr[j]
        k += 1
        j += 1
 
    # Copy back the merged elements to original array*/
    for i in range(left,right+1,1):
        arr[i] = temp[i]
 
    return inv_count
 
#An auxiliary recursive function that sorts the input
# array and returns the number of inversions in the
# array. */
def _mergeSort(arr, temp, left, right):
    inv_count = 0
    if (right > left):
        # Divide the array into two parts and call
        #_mergeSortAndCountInv()
        # for each of the parts */
        mid = int((right + left)/2)
 
        #Inversion count will be sum of inversions in
        # left-part, right-part and number of inversions
        # in merging */
        inv_count = _mergeSort(arr, temp, left, mid)
        inv_count += _mergeSort(arr, temp, mid+1, right)
 
        # Merge the two parts*/
        inv_count += merge(arr, temp, left, mid+1, right)
 
    return inv_count
 
#This function sorts the input array and returns the
#number of inversions in the array */
def countSwaps(arr, n):
    temp = [0 for i in range(n)]
    return _mergeSort(arr, temp, 0, n - 1)
 
# Driver program to test above functions */
if __name__ == '__main__':
    arr = [1, 20, 6, 4, 5]
    n = len(arr)
    print("Number of swaps is",countSwaps(arr, n))
     
 
# This code is contributed by
# Surendra_Gangwar


C#




// C# program to count number of
// swaps required to sort an array
// when only swapping of adjacent
// elements is allowed.
using System;
 
class GFG
{
     
// This function merges two
// sorted arrays and returns
// inversion count in the arrays.
static int merge(int []arr, int []temp,
                 int left, int mid,
                 int right)
{
    int inv_count = 0;
 
    /* i is index for
    left subarray*/
    int i = left;
     
    /* j is index for
    right subarray*/
    int j = mid;
     
    /* k is index for resultant
    merged subarray*/
    int k = left;
     
    while ((i <= mid - 1) &&
           (j <= right))
    {
        if (arr[i] <= arr[j])
            temp[k++] = arr[i++];
        else
        {
            temp[k++] = arr[j++];
 
            /* this is tricky -- see above /
            explanation diagram for merge()*/
            inv_count = inv_count + (mid - i);
        }
    }
 
    /* Copy the remaining elements
    of left subarray (if there are
    any) to temp*/
    while (i <= mid - 1)
        temp[k++] = arr[i++];
 
    /* Copy the remaining elements
    of right subarray (if there are
    any) to temp*/
    while (j <= right)
        temp[k++] = arr[j++];
 
    /*Copy back the merged
    elements to original array*/
    for (i=left; i <= right; i++)
        arr[i] = temp[i];
 
    return inv_count;
}
 
// An auxiliary recursive function
// that sorts the input array and
// returns the number of inversions
// in the array.
static int _mergeSort(int []arr, int []temp,
                      int left, int right)
{
    int mid, inv_count = 0;
    if (right > left)
    {
        // Divide the array into two parts
        // and call _mergeSortAndCountInv()
        // for each of the parts
        mid = (right + left) / 2;
 
        /* Inversion count will be sum of
        inversions in left-part, right-part
        and number of inversions in merging */
        inv_count = _mergeSort(arr, temp,
                               left, mid);
                                 
        inv_count += _mergeSort(arr, temp,
                                mid + 1, right);
 
        /*Merge the two parts*/
        inv_count += merge(arr, temp,
                           left, mid + 1, right);
    }
 
    return inv_count;
}
 
// This function sorts the input
// array and returns the number
// of inversions in the array
static int countSwaps(int []arr, int n)
{
    int []temp = new int[n];
    return _mergeSort(arr, temp, 0, n - 1);
}
 
// Driver Code
public static void Main ()
{
 
    int []arr = {1, 20, 6, 4, 5};
    int n = arr.Length;
        Console.Write("Number of swaps is " +
                         countSwaps(arr, n));
    }
}
 
// This code is contributed by nitin mittal.


PHP




<?php
// PHP program to count number of swaps required
// to sort an array when only swapping of adjacent
// elements is allowed.
  
/* This function merges two sorted arrays and returns inversion
   count in the arrays.*/
function merge(&$arr, &$temp, $left, $mid, $right)
{
    $inv_count = 0;
  
    $i = $left; /* i is index for left subarray*/
    $j = $mid/* j is index for right subarray*/
    $k = $left; /* k is index for resultant merged subarray*/
    while (($i <= $mid - 1) && ($j <= $right))
    {
        if ($arr[$i] <= $arr[$j])
            $temp[$k++] = $arr[$i++];
        else
        {
            $temp[$k++] = $arr[$j++];
  
            /* this is tricky -- see above explanation/
              diagram for merge()*/
            $inv_count = $inv_count + ($mid - $i);
        }
    }
  
    /* Copy the remaining elements of left subarray
     (if there are any) to temp*/
    while ($i <= $mid - 1)
        $temp[$k++] = $arr[$i++];
  
    /* Copy the remaining elements of right subarray
     (if there are any) to temp*/
    while ($j <= $right)
        $temp[$k++] = $arr[$j++];
  
    /*Copy back the merged elements to original array*/
    for ($i=$left; $i <= $right; $i++)
        $arr[$i] = $temp[$i];
  
    return $inv_count;
}
  
/* An auxiliary recursive function that sorts the input
   array and returns the number of inversions in the
   array. */
function _mergeSort(&$arr, &$temp, $left, $right)
{
    $inv_count = 0;
    if ($right > $left)
    {
        /* Divide the array into two parts and call
          _mergeSortAndCountInv() for each of the parts */
        $mid = intval(($right + $left)/2);
  
        /* Inversion count will be sum of inversions in
           left-part, right-part and number of inversions
           in merging */
        $inv_count  = _mergeSort($arr, $temp, $left, $mid);
        $inv_count += _mergeSort($arr, $temp, $mid+1, $right);
  
        /*Merge the two parts*/
        $inv_count += merge($arr, $temp, $left, $mid+1, $right);
    }
  
    return $inv_count;
}
  
/* This function sorts the input array and returns the
   number of inversions in the array */
function countSwaps(&$arr, $n)
{
    $temp = array_fill(0,$n,NULL);
    return _mergeSort($arr, $temp, 0, $n - 1);
}
  
/* Driver program to test above functions */
 
$arr = array(1, 20, 6, 4, 5);
$n = sizeof($arr)/sizeof($arr[0]);
echo "Number of swaps is ". countSwaps($arr, $n);
return 0;
?>


Javascript




<script>
// Javascript program to count number of
// swaps required to sort an array
// when only swapping of adjacent
// elements is allowed.
     
    // This function merges two sorted
    // arrays and returns inversion
    // count in the arrays.
    function merge(arr,temp,left,mid,right)
    {
         let inv_count = 0;
   
        /* i is index for left subarray*/
        let i = left;
           
        /* j is index for right subarray*/
        let j = mid;
           
        /* k is index for resultant merged subarray*/
        let k = left;
           
        while ((i <= mid - 1) && (j <= right))
        {
            if (arr[i] <= arr[j])
                temp[k++] = arr[i++];
            else
            {
                temp[k++] = arr[j++];
       
                /* this is tricky -- see above /
                 explanation diagram for merge()*/
                inv_count = inv_count + (mid - i);
            }
        }
       
        /* Copy the remaining elements of left
        subarray (if there are any) to temp*/
        while (i <= mid - 1)
            temp[k++] = arr[i++];
       
        /* Copy the remaining elements of right
        subarray (if there are any) to temp*/
        while (j <= right)
            temp[k++] = arr[j++];
       
        /*Copy back the merged elements
        to original array*/
        for (i=left; i <= right; i++)
            arr[i] = temp[i];
       
        return inv_count;
    }
     
    // An auxiliary recursive function that
    // sorts the input array and returns
    // the number of inversions in the array.
    function _mergeSort(arr,temp,left,right)
    {
        let mid, inv_count = 0;
        if (right > left)
        {
            // Divide the array into two parts and
            // call _mergeSortAndCountInv() for
            // each of the parts
            mid = Math.floor((right + left)/2);
       
            /* Inversion count will be sum of
            inversions in left-part, right-part
            and number of inversions in merging */
            inv_count = _mergeSort(arr, temp,
                                    left, mid);
                                       
            inv_count += _mergeSort(arr, temp,
                                    mid+1, right);
       
            /*Merge the two parts*/
            inv_count += merge(arr, temp,
                            left, mid+1, right);
        }
       
        return inv_count;
    }
     
    // This function sorts the input
    // array and returns the number
    // of inversions in the array
    function countSwaps(arr,n)
    {
        let temp = new Array(n);
        for(let i = 0; i < n; i++)
        {
            temp[i] = 0;
        }
        return _mergeSort(arr, temp, 0, n - 1);
    }
     
    // Driver Code
    let arr=[1, 20, 6, 4, 5];
    let n = arr.length;
    document.write("Number of swaps is "
                           + countSwaps(arr, n));
                            
    // This code is contributed by rag2127
</script>


Output

Number of swaps is 5 

Time Complexity: O(n Log n)
Auxiliary Space: O(n)

Related Post : 
Minimum number of swaps required to sort an array 

 



Last Updated : 29 Sep, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads