Given a permuted array of length N of first N natural numbers, we need to tell the minimum number of swaps required in the sorted array of first N natural number to reach given permuted array where a number can be swapped with at most 2 positions left to it. If it is not possible to reach permuted array by above swap condition then print not possible.
Examples:
Input : arr = [1, 2, 5, 3, 4] Output : 2 We can reach to above-permuted array in total 2 swaps as shown below, [1, 2, 3, 4, 5] -> [1, 2, 3, 5, 4] -> [1, 2, 5, 3, 4] Input : arr[] = [5, 1, 2, 3, 4] Output : Not Possible It is not possible to reach above array just by swapping numbers 2 positions left to it.
We can solve this problem using inversions. As we can see that if a number is at a position which is more than 2 places away from its actual position then it is not possible to reach there just by swapping with elements at 2 left positions and if all element satisfy this property (there are <=2 elements smaller than it on the right) then answer will simply be a total number of inversions in the array because that many swaps will be needed to transform the array into permuted array.
We can find the number of inversions in N log N time using merge sort technique explained here so total time complexity of solution will be O(N log N) only.
Implementation:
// C++ program to find minimum number of swaps // to reach a permutation with at most 2 left // swaps allowed for every element #include <bits/stdc++.h> using namespace std;
/* 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++];
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 mergeSort( int arr[], int array_size)
{ int *temp = ( int *) malloc ( sizeof ( int )*array_size);
return _mergeSort(arr, temp, 0, array_size - 1);
} // method returns minimum number of swaps to reach // permuted array 'arr' int minSwapToReachArr( int arr[], int N)
{ // loop over all elements to check Invalid
// permutation condition
for ( int i = 0; i < N; i++)
{
/* if an element is at distance more than 2
from its actual position then it is not
possible to reach permuted array just
by swapping with 2 positions left elements
so returning -1 */
if ((arr[i] - 1) - i > 2)
return -1;
}
/* If permuted array is not Invalid, then number
of Inversion in array will be our final answer */
int numOfInversion = mergeSort(arr, N);
return numOfInversion;
} // Driver code to test above methods int main()
{ // change below example
int arr[] = {1, 2, 5, 3, 4};
int N = sizeof (arr) / sizeof ( int );
int res = minSwapToReachArr(arr, N);
if (res == -1)
cout << "Not Possible\n" ;
else
cout << res << endl;
return 0;
} |
// Java program to find minimum // number of swaps to reach a // permutation with at most 2 left // swaps allowed for every element import java.io.*;
public 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 ;
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++];
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 mergeSort( int arr[], int array_size)
{
int [] temp = new int [array_size];
return _mergeSort(arr, temp, 0 , array_size - 1 );
}
// method returns minimum number of
// swaps to reach permuted array 'arr'
static int minSwapToReachArr( int arr[], int N)
{
// loop over all elements to check Invalid
// permutation condition
for ( int i = 0 ; i < N; i++)
{
/* if an element is at distance more than 2
from its actual position then it is not
possible to reach permuted array just
by swapping with 2 positions left elements
so returning -1 */
if ((arr[i] - 1 ) - i > 2 )
{
return - 1 ;
}
}
/* If permuted array is not Invalid, then number
of Inversion in array will be our final answer */
int numOfInversion = mergeSort(arr, N);
return numOfInversion;
}
// Driver code
public static void main(String[] args)
{
// change below example
int arr[] = { 1 , 2 , 5 , 3 , 4 };
int N = arr.length;
int res = minSwapToReachArr(arr, N);
System.out.println(res == - 1 ? "Not Possible\n" : res);
}
} // This code contributed by Rajput-Ji |
# Python3 program to find minimum number of # swaps to reach a permutation with at most # 2 left swaps allowed for every element # 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, i = k + 1 , i + 1
else :
temp[k] = arr[j]
k, j = k + 1 , j + 1
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, 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, j = k + 1 , j + 1
# Copy back the merged elements to original array
for i in range (left, right + 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 = (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 mergeSort(arr, array_size):
temp = [ None ] * array_size
return _mergeSort(arr, temp, 0 , array_size - 1 )
# method returns minimum number of # swaps to reach permuted array 'arr' def minSwapToReachArr(arr, N):
# loop over all elements to check
# Invalid permutation condition
for i in range ( 0 , N):
# if an element is at distance more than 2
# from its actual position then it is not
# possible to reach permuted array just
# by swapping with 2 positions left elements
# so returning -1
if (arr[i] - 1 ) - i > 2 :
return - 1
# If permuted array is not Invalid, then number
# of Inversion in array will be our final answer
numOfInversion = mergeSort(arr, N)
return numOfInversion
# Driver code to test above methods if __name__ = = "__main__" :
# change below example
arr = [ 1 , 2 , 5 , 3 , 4 ]
N = len (arr)
res = minSwapToReachArr(arr, N)
if res = = - 1 :
print ( "Not Possible" )
else :
print (res)
# This code is contributed by Rituraj Jain |
// C# program to find minimum // number of swaps to reach a // permutation with at most 2 left // swaps allowed for every element 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;
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++];
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 mergeSort( int []arr, int array_size)
{
int [] temp = new int [array_size];
return _mergeSort(arr, temp, 0, array_size - 1);
}
// method returns minimum number of
// swaps to reach permuted array 'arr'
static int minSwapToReachArr( int []arr, int N)
{
// loop over all elements to check Invalid
// permutation condition
for ( int i = 0; i < N; i++)
{
/* if an element is at distance more than 2
from its actual position then it is not
possible to reach permuted array just
by swapping with 2 positions left elements
so returning -1 */
if ((arr[i] - 1) - i > 2)
{
return -1;
}
}
/* If permuted array is not Invalid, then number
of Inversion in array will be our final answer */
int numOfInversion = mergeSort(arr, N);
return numOfInversion;
}
// Driver code
static void Main()
{
// change below example
int []arr = {1, 2, 5, 3, 4};
int N = arr.Length;
int res = minSwapToReachArr(arr, N);
if (res == -1)
Console.WriteLine( "Not Possible" );
else
Console.WriteLine(res);
}
} // This code is contributed by mits |
<script> // JavaScript program to find minimum // number of swaps to reach a // permutation with at most 2 left // swaps allowed for every element /* This function merges two sorted
arrays and returns inversion
count in the arrays.*/
function merge(arr, temp, left,
mid, right)
{
let inv_count = 0;
let i = left;
/* i is index for left subarray*/
let j = mid;
/* j is index for right subarray*/
let 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++];
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 = (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 mergeSort(arr, array_size)
{
let temp = Array.from({length: array_size}, (_, i) => 0);
return _mergeSort(arr, temp, 0, array_size - 1);
}
// method returns minimum number of
// swaps to reach permuted array 'arr'
function minSwapToReachArr(arr, N)
{
// loop over all elements to check Invalid
// permutation condition
for (let i = 0; i < N; i++)
{
/* if an element is at distance more than 2
from its actual position then it is not
possible to reach permuted array just
by swapping with 2 positions left elements
so returning -1 */
if ((arr[i] - 1) - i > 2)
{
return -1;
}
}
/* If permuted array is not Invalid, then number
of Inversion in array will be our final answer */
let numOfInversion = mergeSort(arr, N);
return numOfInversion;
}
// Driver Code // change below example
let arr = [1, 2, 5, 3, 4];
let N = arr.length;
let res = minSwapToReachArr(arr, N);
document.write(res == -1 ? "Not Possible\n" : res);
</script> |
2
Time Complexity: O(N*logN)
Auxiliary Space: O(logN)