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:
- A sorted array has no inversions.
- An adjacent swap can reduce one inversion. Doing x adjacent swaps can reduce x inversions in an array.
Implementation:
// 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 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 |
# 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# 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 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;
?> |
<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> |
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