Minimum swaps so that binary search can be applied

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 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 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 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 position of k is lesser than mid. Now, in this case, 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 right position so this will not be used in any swap so here we have to decrease the one of it’s greater available element i.e. from num_max. Same goes with the case when arr[mid] is lesser than k and position of k is greater than mid. Here, we have to decrease one of it’s smaller available element 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. total number of greater elements from k that are still available for swapping and num_min i.e. 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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP program to find Minimum number
// of swaps to get the position of
// the element if we provide an
// unsorted array to binary search.
#include <bits/stdc++.h>
using namespace std;
  
// Function to find minimum swaps.
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;
  
    // Here we are getting number of
    // smaller and greater elements of k.
    for (int i = 0; i < n; i++) {
        if (arr[i] < k)
            num_min++;
  
        else if (arr[i] > k)
            num_max++;
    }
  
    // Here we are calculating the actual
    // position of k in the array.
    for (int i = 0; i < n; i++) {
        if (arr[i] == k) {
            pos = i;
            break;
        }
    }
  
    int left, right, mid;
    left = 0;
    right = n - 1;
  
    // Implementing binary search as
    // per the above-discussed cases.
    while (left <= right) {
        mid = (left + right) / 2;
  
        // If we find the k.
        if (arr[mid] == k) {
            break;
        }
  
        else if (arr[mid] > k) {
  
            // If we need minimum
            // element swap.
            if (pos > mid)
                need_minimum++;
  
            else
  
                // Else the element is
                // at the right position.
                num_min--;
  
            left = mid + 1;
        }
  
        else {
            if (pos < mid)
  
                // If we need maximum
                // element swap.
                need_maximum++;
  
            else
  
                // Else element is at
                // the right position
                num_max--;
  
            right = mid - 1;
        }
    }
  
    // Calculating the required swaps.
    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 it is impossible.
    if (need_maximum > num_max || need_minimum > num_min)
        return -1;
  
    else
        return (swaps + need_maximum + need_minimum);
}
  
// Driver function
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);
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

//Java program to find Minimum number
// of swaps to get the position of
// the element if we provide an
// unsorted array to binary search.
public class GFG {
  
// Function to find minimum swaps.
    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;
  
        // Here we are getting number of
        // smaller and greater elements of k.
        for (int i = 0; i < n; i++) {
            if (arr[i] < k) {
                num_min++;
            } else if (arr[i] > k) {
                num_max++;
            }
        }
  
        // Here we are calculating the actual
        // position of k in the array.
        for (int i = 0; i < n; i++) {
            if (arr[i] == k) {
                pos = i;
                break;
            }
        }
  
        int left, right, mid;
        left = 0;
        right = n - 1;
  
        // Implementing binary search as
        // per the above-discussed cases.
        while (left <= right) {
            mid = (left + right) / 2;
  
            // If we find the k.
            if (arr[mid] == k) {
                break;
            } else if (arr[mid] > k) {
  
                // If we need minimum
                // element swap.
                if (pos > mid) {
                    need_minimum++;
                } else // Else the element is
                // at the right position.
                {
                    num_min--;
                }
  
                left = mid + 1;
            } else {
                if (pos < mid) // If we need maximum
                // element swap.
                {
                    need_maximum++;
                } else // Else element is at
                // the right position
                {
                    num_max--;
                }
  
                right = mid - 1;
            }
        }
  
        // Calculating the required swaps.
        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 it is impossible.
        if (need_maximum > num_max || need_minimum > num_min) {
            return -1;
        } else {
            return (swaps + need_maximum + need_minimum);
        }
    }
  
// Driver function
    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));
    }
  
}
  
/*This code is contributed by PrinciRaj1992*/

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to find Minimum number 
// of swaps to get the position of 
// the element if we provide an 
// unsorted array to binary search. 
  
using System;
public class GFG{
  
  
// Function to find minimum swaps. 
    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; 
  
        // Here we are getting number of 
        // smaller and greater elements of k. 
        for (int i = 0; i < n; i++) { 
            if (arr[i] < k) { 
                num_min++; 
            } else if (arr[i] > k) { 
                num_max++; 
            
        
  
        // Here we are calculating the actual 
        // position of k in the array. 
        for (int i = 0; i < n; i++) { 
            if (arr[i] == k) { 
                pos = i; 
                break
            
        
  
        int left, right, mid; 
        left = 0; 
        right = n - 1; 
  
        // Implementing binary search as 
        // per the above-discussed cases. 
        while (left <= right) { 
            mid = (left + right) / 2; 
  
            // If we find the k. 
            if (arr[mid] == k) { 
                break
            } else if (arr[mid] > k) { 
  
                // If we need minimum 
                // element swap. 
                if (pos > mid) { 
                    need_minimum++; 
                } else // Else the element is 
                // at the right position. 
                
                    num_min--; 
                
  
                left = mid + 1; 
            } else
                if (pos < mid) // If we need maximum 
                // element swap. 
                
                    need_maximum++; 
                } else // Else element is at 
                // the right position 
                
                    num_max--; 
                
  
                right = mid - 1; 
            
        
  
        // Calculating the required swaps. 
        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 it is impossible. 
        if (need_maximum > num_max || need_minimum > num_min) { 
            return -1; 
        } else
            return (swaps + need_maximum + need_minimum); 
        
    
  
// Driver function 
    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)); 
    
  
  
/*This code is contributed by PrinciRaj1992*/

chevron_right



Output:

2


My Personal Notes arrow_drop_up

Intern at GeeksforGeeks

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Article Tags :
Practice Tags :


1


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.