Minimum swaps so that binary search can be applied
Last Updated :
23 Jun, 2022
Given an unsorted array of length n and an integer k, find the minimum swaps to get the position of k before using the binary search. Here we can swap any two numbers as many times as we want. If we cannot get the position by swapping elements, print “-1”.
Examples:
Input : arr = {3, 10, 6, 7, 2, 5, 4}
k = 4
Output : 2
Explanation :
Here, after swapping 3 with 7 and 2 with 5, the
final array will look like {7, 10, 6, 3, 5, 2, 4}.
Now, if we provide this array to binary search we
can get the position of 4.
Input : arr = {3, 10, 6, 7, 2, 5, 4}
k = 10
Output : -1
Explanation :
Here, we can not get the position of 10 if we
provide this array to the binary search even
not with swapping some pairs.
Approach: Before discussing the approach, we have to assume that here we are not supposed to swap the pairs. We just need to count the minimum number of swaps so that if we provide the newly created array to the binary search, we can get the position of k. In order to do so, we need to pass the given array to binary search and focus on the following things:-
- Before going to the binary search we need to calculate the number of minimum elements i.e. num_min of k and the number of maximum elements i.e. num_max of k. Here, num_min denotes the number of smaller available elements of k and num_max denotes the number of greater available elements that we can use for swapping
- The actual position of k in the given array.
Now following are the test cases that will occur during implementing the binary search:-
Case 1: If arr[mid] is greater than k, but the position of k is greater than mid. Binary search would take us to (arr[0] to arr[mid-1]). But actually our element is in between (arr[mid+1] to arr[last element]). So, in order to go in the right direction, we need something smaller than k so that we can swap it with arr[mid] and we can go between arr[mid+1] to arr[last_element]. So, here we require one swap i.e. need_minimum.
Case 2: If arr[mid] is less than k but the position of k is smaller than mid. Binary search would take us to (arr[mid+1] to arr[last_element]). But actually our element is in between (arr[0] to arr[mid-1]). So, in order to go in the right direction, we need something greater than k so that we can swap it with arr[mid] and we can go between arr[0] to arr[mid-1]. So, here we required one swap i.e. need_maximum.
Case 3:
If arr[mid] is greater than k and the position of k is lesser than mid. Now, in this case, the binary search would work fine. But wait, here is the important thing on which we have to work on. As we know in this case binary search will work fine, arr[mid] is at the right position so this will not be used in any swap so here we have to decrease one of its greater available elements i.e. from num_max. The same goes with the case when arr[mid] is lesser than k and the position of k is greater than mid. Here, we have to decrease one of its smaller available elements i.e. from num_min.
Case 4: If arr[mid] == k Or pos == mid then we can easily come out from the binary search.
So, till now we have calculated the need_minimum i.e. number of minimum elements required for swapping, need_maximum i.e. number of maximum elements required for swapping, num_max i.e. a total number of greater elements from k that are still available for swapping, and num_min i.e. the total number of minimum elements from k that are available for swapping.
Now here we have to consider two cases:
Case 1: If need_minimum is greater than need_maximum. In this case, we have to swap all these needed maximum elements with the smaller of k. So we have to use the smaller elements from num_min. Now all the need_maximum swaps are done. Here the main thing is that when we swapped all these needed maximum elements with smaller elements, these smaller elements got their right positions. So, indirectly we have done some of the needed smaller elements swaps and that will be calculated as need_minimum – need_maximum and also available num_min will be num_min – need_maximum. Now, we have to calculate the remaining need_minimum swaps. We can calculate these swaps if we have enough num_min i.e. num_min > need_minimum. For this case, swaps will be need_maximum + need_minimum otherwise it will be -1. The same concept goes with the case when we have need_minimum is smaller than need_maximum.
Below is the basic implementation of the above approach:-
C++
#include <bits/stdc++.h>
using namespace std;
int findMinimumSwaps( int * arr, int n,
int k)
{
int pos, num_min, num_max,
need_minimum, need_maximum, swaps;
num_min = num_max = need_minimum = 0;
need_maximum = swaps = 0;
for ( int i = 0; i < n; i++) {
if (arr[i] < k)
num_min++;
else if (arr[i] > k)
num_max++;
}
for ( int i = 0; i < n; i++) {
if (arr[i] == k) {
pos = i;
break ;
}
}
int left, right, mid;
left = 0;
right = n - 1;
while (left <= right) {
mid = (left + right) / 2;
if (arr[mid] == k) {
break ;
}
else if (arr[mid] > k) {
if (pos > mid)
need_minimum++;
else
num_min--;
left = mid + 1;
}
else {
if (pos < mid)
need_maximum++;
else
num_max--;
right = mid - 1;
}
}
if (need_minimum > need_maximum) {
swaps = swaps + need_maximum;
num_min = num_min - need_maximum;
need_minimum = need_minimum - need_maximum;
need_maximum = 0;
}
else {
swaps = swaps + need_minimum;
num_max = num_max - need_minimum;
need_maximum = need_maximum - need_minimum;
need_minimum = 0;
}
if (need_maximum > num_max || need_minimum > num_min)
return -1;
else
return (swaps + need_maximum + need_minimum);
}
int main()
{
int arr[] = { 3, 10, 6, 7, 2, 5, 4 }, k = 4;
int n = sizeof (arr) / sizeof (arr[0]);
cout << findMinimumSwaps(arr, n, k);
}
|
Java
public class GFG {
static int findMinimumSwaps( int [] arr, int n,
int k) {
int pos = 0 , num_min, num_max,
need_minimum, need_maximum, swaps;
num_min = num_max = need_minimum = 0 ;
need_maximum = swaps = 0 ;
for ( int i = 0 ; i < n; i++) {
if (arr[i] < k) {
num_min++;
} else if (arr[i] > k) {
num_max++;
}
}
for ( int i = 0 ; i < n; i++) {
if (arr[i] == k) {
pos = i;
break ;
}
}
int left, right, mid;
left = 0 ;
right = n - 1 ;
while (left <= right) {
mid = (left + right) / 2 ;
if (arr[mid] == k) {
break ;
} else if (arr[mid] > k) {
if (pos > mid) {
need_minimum++;
} else
{
num_min--;
}
left = mid + 1 ;
} else {
if (pos < mid)
{
need_maximum++;
} else
{
num_max--;
}
right = mid - 1 ;
}
}
if (need_minimum > need_maximum) {
swaps = swaps + need_maximum;
num_min = num_min - need_maximum;
need_minimum = need_minimum - need_maximum;
need_maximum = 0 ;
} else {
swaps = swaps + need_minimum;
num_max = num_max - need_minimum;
need_maximum = need_maximum - need_minimum;
need_minimum = 0 ;
}
if (need_maximum > num_max || need_minimum > num_min) {
return - 1 ;
} else {
return (swaps + need_maximum + need_minimum);
}
}
public static void main(String[] args) {
int arr[] = { 3 , 10 , 6 , 7 , 2 , 5 , 4 }, k = 4 ;
int n = arr.length;
System.out.println(findMinimumSwaps(arr, n, k));
}
}
|
Python3
def findMinimumSwaps(arr,
n, k):
num_min = num_max = need_minimum = 0
need_maximum = swaps = 0
for i in range (n):
if (arr[i] < k):
num_min + = 1
elif (arr[i] > k):
num_max + = 1
for i in range (n):
if (arr[i] = = k):
pos = i
break
left = 0
right = n - 1
while (left < = right):
mid = (left + right) / / 2
if (arr[mid] = = k):
break
elif (arr[mid] > k):
if (pos > mid):
need_minimum + = 1
else :
num_min - = 1
left = mid + 1
else :
if (pos < mid):
need_maximum + = 1
else :
num_max - = 1
right = mid - 1
if (need_minimum > need_maximum):
swaps = swaps + need_maximum
num_min = num_min - need_maximum
need_minimum = (need_minimum -
need_maximum)
need_maximum = 0
else :
swaps = swaps + need_minimum
num_max = num_max - need_minimum
need_maximum = (need_maximum -
need_minimum)
need_minimum = 0
if (need_maximum > num_max or
need_minimum > num_min):
return - 1
else :
return (swaps + need_maximum +
need_minimum)
if __name__ = = "__main__" :
arr = [ 3 , 10 , 6 , 7 , 2 , 5 , 4 ]
k = 4
n = len (arr)
print (findMinimumSwaps(arr, n, k))
|
C#
using System;
public class GFG{
static int findMinimumSwaps( int [] arr, int n,
int k) {
int pos = 0, num_min, num_max,
need_minimum, need_maximum, swaps;
num_min = num_max = need_minimum = 0;
need_maximum = swaps = 0;
for ( int i = 0; i < n; i++) {
if (arr[i] < k) {
num_min++;
} else if (arr[i] > k) {
num_max++;
}
}
for ( int i = 0; i < n; i++) {
if (arr[i] == k) {
pos = i;
break ;
}
}
int left, right, mid;
left = 0;
right = n - 1;
while (left <= right) {
mid = (left + right) / 2;
if (arr[mid] == k) {
break ;
} else if (arr[mid] > k) {
if (pos > mid) {
need_minimum++;
} else
{
num_min--;
}
left = mid + 1;
} else {
if (pos < mid)
{
need_maximum++;
} else
{
num_max--;
}
right = mid - 1;
}
}
if (need_minimum > need_maximum) {
swaps = swaps + need_maximum;
num_min = num_min - need_maximum;
need_minimum = need_minimum - need_maximum;
need_maximum = 0;
} else {
swaps = swaps + need_minimum;
num_max = num_max - need_minimum;
need_maximum = need_maximum - need_minimum;
need_minimum = 0;
}
if (need_maximum > num_max || need_minimum > num_min) {
return -1;
} else {
return (swaps + need_maximum + need_minimum);
}
}
public static void Main() {
int []arr = {3, 10, 6, 7, 2, 5, 4};
int k = 4;
int n = arr.Length;
Console.WriteLine(findMinimumSwaps(arr, n, k));
}
}
|
Javascript
<script>
function findMinimumSwaps(arr, n, k)
{
let pos, num_min, num_max,
need_minimum, need_maximum, swaps;
num_min = num_max = need_minimum = 0;
need_maximum = swaps = 0;
for (let i = 0; i < n; i++) {
if (arr[i] < k)
num_min++;
else if (arr[i] > k)
num_max++;
}
for (let i = 0; i < n; i++) {
if (arr[i] == k) {
pos = i;
break ;
}
}
let left, right, mid;
left = 0;
right = n - 1;
while (left <= right) {
mid = parseInt((left + right) / 2, 10);
if (arr[mid] == k) {
break ;
}
else if (arr[mid] > k) {
if (pos > mid)
need_minimum++;
else
num_min--;
left = mid + 1;
}
else {
if (pos < mid)
need_maximum++;
else
num_max--;
right = mid - 1;
}
}
if (need_minimum > need_maximum) {
swaps = swaps + need_maximum;
num_min = num_min - need_maximum;
need_minimum = need_minimum - need_maximum;
need_maximum = 0;
}
else {
swaps = swaps + need_minimum;
num_max = num_max - need_minimum;
need_maximum = need_maximum - need_minimum;
need_minimum = 0;
}
if (need_maximum > num_max || need_minimum > num_min)
return -1;
else
return (swaps + need_maximum + need_minimum);
}
let arr = [ 3, 10, 6, 7, 2, 5, 4 ], k = 4;
let n = arr.length;
document.write(findMinimumSwaps(arr, n, k));
</script>
|
Output:
2
Time Complexity: O(n)
Auxiliary Space: O(1)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...