📌  相关文章
📜  通过从给定的 Array 中选择 K 个元素来最大化任何元素对之间的最小差异

📅  最后修改于: 2022-05-13 01:56:06.540000             🧑  作者: Mango

通过从给定的 Array 中选择 K 个元素来最大化任何元素对之间的最小差异

给定一个由N个整数组成的数组,任务是从这N个元素中选择K个元素,使得每个 K 个数之间的最小差是最大的。返回 选择任意K个元素后的最大最小差值。

例子:

朴素方法:生成所有大小为 K 的子集并找到所有子集的最小差异。然后返回差异中的最大值。

有效的方法:给定的问题可以使用对答案技术的二分搜索来有效地解决。可以按照以下步骤解决问题:

  • 按升序对数组进行排序
  • 将最小答案ans初始化为 1
  • 二进制搜索用于数组arr中从 1 到最大元素的范围
  • 变量diff用于存储每次迭代时的最大最小差异
  • 辅助函数用于检查是否可以选择K个元素,且最小差异大于先前迭代中计算的差异。如果可能,则返回 true,否则返回 false。
  • 如果上述函数返回:
    • True 然后将ans更新为dif并左更新为dif + 1
    • False 然后将权限更新为差异- 1

下面是上述二分查找方法的实现

C++
// C++ implementation for the above approach
#include 
using namespace std;
 
// To check if selection of K elements
// is possible such that difference
// between them is greater than dif
bool isPossibleToSelect(int arr[], int N,
                        int dif, int K)
{
    // Selecting first element in the
    // sorted array
    int count = 1;
 
    // prev is the previously selected
    // element initially at index 0 as
    // first element is already selected
    int prev = arr[0];
 
    // Check if selection of K-1 elements
    // from array with a minimum
    // difference of dif is possible
    for (int i = 1; i < N; i++) {
 
        // If the current element is
        // atleast dif difference apart
        // from the  previously selected
        // element then select the current
        // element and increase the count
        if (arr[i] >= (prev + dif)) {
            count++;
 
            // If selection of K elements
            // with a min difference of dif
            // is possible then return true
            if (count == K)
                return true;
 
            // Prev will become current
            // element for the next iteration
            prev = arr[i];
        }
    }
    // If selection of K elements with minimum
    // difference of dif is not possible
    // then return false
    return false;
}
 
int binarySearch(int arr[], int left,
                 int right, int K, int N)
{
    // Minimum largest difference
    // possible is 1
    int ans = 1;
    while (left <= right) {
        int dif = left + (right - left) / 2;
 
        // Check if selection of K elements
        // is possible with a minimum
        // difference of dif
        if (isPossibleToSelect(arr, N,
                               dif, K)) {
 
            // If dif is greater than
            // previous ans we update ans
            ans = max(ans, dif);
 
            // Continue to search for better
            // answer. Try finding greater dif
            left = dif + 1;
        }
 
        // K elements cannot be selected
        else
            right = dif - 1;
    }
    return ans;
}
 
// Driver code
int main()
{
    int N, K;
    N = 7, K = 4;
    int arr[] = { 1, 4, 9, 0, 2, 13, 3 };
 
    // arr should be in a sorted order
    sort(arr, arr + N);
 
    cout << binarySearch(arr, 0, arr[N - 1], K, N)
         << "\n";
    return 0;
}


Java
// Java implementation for the above approach
import java.io.*;
import java.util.Arrays;
 
class GFG{
 
  // To check if selection of K elements
  // is possible such that difference
  // between them is greater than dif
  static boolean isPossibleToSelect(int []arr, int N,
                                    int dif, int K)
  {
 
    // Selecting first element in the
    // sorted array
    int count = 1;
 
    // prev is the previously selected
    // element initially at index 0 as
    // first element is already selected
    int prev = arr[0];
 
    // Check if selection of K-1 elements
    // from array with a minimum
    // difference of dif is possible
    for (int i = 1; i < N; i++) {
 
      // If the current element is
      // atleast dif difference apart
      // from the  previously selected
      // element then select the current
      // element and increase the count
      if (arr[i] >= (prev + dif)) {
        count++;
 
        // If selection of K elements
        // with a min difference of dif
        // is possible then return true
        if (count == K)
          return true;
 
        // Prev will become current
        // element for the next iteration
        prev = arr[i];
      }
    }
    // If selection of K elements with minimum
    // difference of dif is not possible
    // then return false
    return false;
  }
 
  static int binarySearch(int []arr, int left,
                          int right, int K, int N)
  {
    // Minimum largest difference
    // possible is 1
    int ans = 1;
    while (left <= right) {
      int dif = left + (right - left) / 2;
 
      // Check if selection of K elements
      // is possible with a minimum
      // difference of dif
      if (isPossibleToSelect(arr, N,
                             dif, K)) {
 
        // If dif is greater than
        // previous ans we update ans
        ans = Math.max(ans, dif);
 
        // Continue to search for better
        // answer. Try finding greater dif
        left = dif + 1;
      }
 
      // K elements cannot be selected
      else
        right = dif - 1;
    }
    return ans;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int N, K;
    N = 7;
    K = 4;
    int []arr = { 1, 4, 9, 0, 2, 13, 3 };
 
    // arr should be in a sorted order
    Arrays.sort(arr);
 
    System.out.println(binarySearch(arr, 0, arr[N - 1], K, N));
  }
}
 
// This code is contributed by shivanisinghss2110


Python3
# Python 3 implementation for the above approach
 
# To check if selection of K elements
# is possible such that difference
# between them is greater than dif
def isPossibleToSelect(arr, N,
                       dif, K):
 
    # Selecting first element in the
    # sorted array
    count = 1
 
    # prev is the previously selected
    # element initially at index 0 as
    # first element is already selected
    prev = arr[0]
 
    # Check if selection of K-1 elements
    # from array with a minimum
    # difference of dif is possible
    for i in range(1, N):
 
        # If the current element is
        # atleast dif difference apart
        # from the  previously selected
        # element then select the current
        # element and increase the count
        if (arr[i] >= (prev + dif)):
            count += 1
 
            # If selection of K elements
            # with a min difference of dif
            # is possible then return true
            if (count == K):
                return True
 
            # Prev will become current
            # element for the next iteration
            prev = arr[i]
    # If selection of K elements with minimum
    # difference of dif is not possible
    # then return false
    return False
 
 
def binarySearch(arr, left,
                 right, K,  N):
    # Minimum largest difference
    # possible is 1
    ans = 1
    while (left <= right):
        dif = left + (right - left) // 2
 
        # Check if selection of K elements
        # is possible with a minimum
        # difference of dif
        if (isPossibleToSelect(arr, N, dif, K)):
 
            # If dif is greater than
            # previous ans we update ans
            ans = max(ans, dif)
 
            # Continue to search for better
            # answer. Try finding greater dif
            left = dif + 1
 
        # K elements cannot be selected
        else:
            right = dif - 1
 
    return ans
 
# Driver code
if __name__ == "__main__":
 
    N = 7
    K = 4
    arr = [1, 4, 9, 0, 2, 13, 3]
 
    # arr should be in a sorted order
    arr.sort()
 
    print(binarySearch(arr, 0, arr[N - 1], K, N)
          )
 
    # This code is contributed by ukasp.


C#
// C# implementation for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// To check if selection of K elements
// is possible such that difference
// between them is greater than dif
static bool isPossibleToSelect(int []arr, int N,
                        int dif, int K)
{
    // Selecting first element in the
    // sorted array
    int count = 1;
 
    // prev is the previously selected
    // element initially at index 0 as
    // first element is already selected
    int prev = arr[0];
 
    // Check if selection of K-1 elements
    // from array with a minimum
    // difference of dif is possible
    for (int i = 1; i < N; i++) {
 
        // If the current element is
        // atleast dif difference apart
        // from the  previously selected
        // element then select the current
        // element and increase the count
        if (arr[i] >= (prev + dif)) {
            count++;
 
            // If selection of K elements
            // with a min difference of dif
            // is possible then return true
            if (count == K)
                return true;
 
            // Prev will become current
            // element for the next iteration
            prev = arr[i];
        }
    }
    // If selection of K elements with minimum
    // difference of dif is not possible
    // then return false
    return false;
}
 
static int binarySearch(int []arr, int left,
                 int right, int K, int N)
{
    // Minimum largest difference
    // possible is 1
    int ans = 1;
    while (left <= right) {
        int dif = left + (right - left) / 2;
 
        // Check if selection of K elements
        // is possible with a minimum
        // difference of dif
        if (isPossibleToSelect(arr, N,
                               dif, K)) {
 
            // If dif is greater than
            // previous ans we update ans
            ans = Math.Max(ans, dif);
 
            // Continue to search for better
            // answer. Try finding greater dif
            left = dif + 1;
        }
 
        // K elements cannot be selected
        else
            right = dif - 1;
    }
    return ans;
}
 
// Driver code
public static void Main()
{
    int N, K;
    N = 7;
     K = 4;
    int []arr = { 1, 4, 9, 0, 2, 13, 3 };
 
    // arr should be in a sorted order
    Array.Sort(arr);
 
    Console.Write(binarySearch(arr, 0, arr[N - 1], K, N));
}
}
 
// This code is contributed by SURENDRA_GANGWAR.


Javascript


输出
4

时间复杂度: O(N * log N)
空间复杂度: O(1)