📜  最小交换,以便可以应用二进制搜索

📅  最后修改于: 2021-04-23 07:44:59             🧑  作者: Mango

给定长度为n和整数k的未排序数组,请在使用二进制搜索之前找到最小交换以获取k的位置。在这里,我们可以任意交换任意两个数字。如果我们无法通过交换元素获得位置,请打印“ -1”。
例子:

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.

方法:在讨论该方法之前,我们必须假定此处不交换对。我们只需要计算交换的最小数量,这样如果我们将新创建的数组提供给二进制搜索,则可以得到k的位置。为此,我们需要将给定的数组传递给二进制搜索,并专注于以下方面:

  • 在进行二值搜索之前,我们需要计算最小元素的数量,即k的num_min和最大元素的数量,即k的num_max 。在这里,num_min表示k的较小可用元素的数量,num_max表示可用于交换的较大的可用元素的数量
  • k在给定数组中的实际位置

现在,以下是在执行二进制搜索过程中将发生的测试用例:-
情况1:如果arr [mid]大于k,但k的位置大于mid。二进制搜索会将我们带到(arr [0]到arr [mid-1])。但是实际上我们的元素介于两者之间(arr [mid + 1]到arr [last元素])。因此,为了朝正确的方向前进,我们需要小于k的东西,以便可以将其与arr [mid]交换,并且可以在arr [mid + 1]到arr [last_element]之间移动。因此,这里我们需要进行一次交换,即need_minimum
情况2:如果arr [mid]小于k,但k的位置小于mid。二进制搜索会将我们带到(arr [mid + 1]到arr [last_element])。但实际上,我们的元素介于两者之间(arr [0]至arr [mid-1])。因此,为了朝正确的方向前进,我们需要大于k的值,以便可以将其与arr [mid]交换,并且可以在arr [0]到arr [mid-1]之间移动。因此,这里我们需要进行一次交换,即need_maximum
情况3:
如果arr [mid]大于k并且k的位置小于mid。现在,在这种情况下,二进制搜索将可以正常工作。但是,等等,这是我们必须处理的重要事情。众所周知,在这种情况下,二进制搜索可以正常工作,arr [mid]处于正确的位置,因此不会在任何交换中使用它,因此在这里,我们必须减少其较大的可用元素之一,即从num_max。当arr [mid]小于k且k的位置大于mid的情况也是如此。在这里,我们必须减少其较小的可用元素之一,即从num_min开始。
情况4:如果arr [mid] == k或pos == mid,那么我们可以轻松地从二元搜索中得出。
因此,到目前为止,我们已经计算了need_minimum(即交换所需的最小元素数), need_maximum(即交换所需的最大元素数), num_max(即k中仍可用于交换的较大元素的总数)和num_min(即总数)可用于交换的k中的最小元素数。
现在在这里我们必须考虑两种情况:
情况1:如果need_minimum大于need_maximum。在这种情况下,我们必须将所有这些所需的最大元素交换为较小的k。因此,我们必须使用num_min中的较小元素。现在,所有need_maximum交换均已完成。这里最主要的是,当我们将所有这些所需的最大元素交换为较小的元素时,这些较小的元素将获得正确的位置。因此,我们间接完成了一些所需的较小元素交换,这些交换将计算为need_minimum – need_maximum ,可用的num_min也将是num_min – need_maximum 。现在,我们必须计算剩余的need_minimum交换。如果我们有足够的num_min,即num_min> need_minimum,我们可以计算这些掉期。对于这种情况,交换将为need_maximum + need_minimum,否则为-1。当我们的need_minimum小于need_maximum时,同样的概念也适用。
以下是上述方法的基本实现:

C++
// 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 
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);
}


Java
//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*/


Python3
# Python3 program to find Minimum number
# of swaps to get the position of
# the element if we provide an
# unsorted array to binary search.
 
# Function to find minimum swaps.
def findMinimumSwaps(arr,
                     n, k):
 
    num_min = num_max = need_minimum = 0
    need_maximum = swaps = 0
 
    # Here we are getting number of
    # smaller and greater elements of k.
    for i in range(n):
        if (arr[i] < k):
            num_min += 1
 
        elif (arr[i] > k):
            num_max += 1
 
    # Here we are calculating the actual
    # position of k in the array.
    for i in range(n):
        if (arr[i] == k):
            pos = i
            break
 
    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
 
        elif (arr[mid] > k):
            # If we need minimum
            # element swap.
            if (pos > mid):
                need_minimum += 1
 
            else:
 
                # Else the element is
                # at the right position.
                num_min -= 1
 
            left = mid + 1
 
        else:
            if (pos < mid):
 
                # If we need maximum
                # element swap.
                need_maximum += 1
 
            else:
 
                # Else element is at
                # the right position
                num_max -= 1
 
            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 or
        need_minimum > num_min):
        return -1
 
    else:
        return (swaps + need_maximum +
                need_minimum)
 
# Driver function
if __name__ == "__main__":
   
    arr = [3, 10, 6, 7, 2, 5, 4]
    k = 4
    n = len(arr)
    print(findMinimumSwaps(arr, n, k))
 
# This code is contributed by Chitranayal


C#
// 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*/


Javascript


输出:

2