📌  相关文章
📜  最小化范围 [L, R] 以将 Array 划分为 K 个子数组,其中大多数元素在 [L, R] 中

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

最小化范围 [L, R] 以将 Array 划分为 K 个子数组,其中大多数元素在 [L, R] 中

给定一个大小为N的数组arr[] ,任务是找到最小值范围 [L, R]使得:

  • 数组可以分成K个子数组。
  • [L, R] 范围内的元素大于 [l, r] 范围外的元素。

例子:

朴素方法:这可以通过检查从 1 到数组大小的每个大小的范围,然后检查范围内的元素数和范围外的元素数,然后检查它们的差是否大于或等于 K。

时间复杂度: O(N 2 )
辅助空间: 在)

有效的方法:这种方法基于对范围[1, N]的二进制搜索,使用散列技术和前缀总和来跟踪数组中直到i的范围内的元素数量,并检查是否有可能对于可以将数组划分为遵循给定条件的K个子数组的任何范围。请按照上述步骤操作:

  • 初始化计数向量以存储数组元素的频率。
  • 初始化向量前缀和以存储该索引之前的元素数。
  • 现在从[1, N]遍历数组并使用前缀求和技术存储元素的计数直到i
  • 初始化can= 0,l, r来存储范围, low = 0, high = N来对范围的大小执行二分查找。
  • 低 ≤ 高时执行二分查找。
    • mid初始化为(low + high)/2
    • 使用[1, N-mid+1] 中的 for 循环进行迭代,使用i检查大小中间的范围。
      • 现在计算范围[i, i+mid-1]和范围外的元素数。
      • 检查范围内范围外元素的差异是否大于或等于K
    • 将范围存储在l, r中,如果它大于等于K ,则可以 =1
    • 如果有可能,则将mid-1
    • 其他=中 +1
  • 打印范围。

下面是上述方法的实现。

C++
// C++ code for the above approach
 
#include 
using namespace std;
 
// Function to minimize the range
// To divide the array arr
// Into k subarrays that has
// Number of elements in the range
// Greater than out of range
void find_minrange(vector arr, int n, int k)
{
    // Initialize the count vector
    // To store the frequencies
    // Of the elements
    vector count(n + 1);
    for (auto x : arr)
        count[x]++;
 
    // Initialize a vector prefix sum to
    // Store the number of elements till
    // That index
    vector prefixsum(n + 1);
 
    // Now traverse through from[1, n]
    // And store the count of elements till i
    for (int i = 1; i <= n; i++)
        prefixsum[i] = prefixsum[i - 1]
                       + count[i];
 
    int low = 1, high = n;
 
    // Initialize l, r to store the range
    int l, r;
 
    while (low <= high) {
        // Initialize the mid
        int mid = (low + high) / 2;
 
        bool can = false;
 
        // For each range size (mid)
        for (int i = 1; i <= n - mid + 1; i++) {
 
            // Count the number of elements
            // In the range [i, i+mid-1]
            // And out of the range
            int inrange
                = prefixsum[i + mid - 1]
                  - prefixsum[i - 1];
            int outrange = n - inrange;
 
            // Check if the difference of inrange
            // And outrange is greater than
            // or equal to k
            if (inrange - outrange >= k) {
 
                // Store the range
                // Since it is a possible range
                can = true;
                l = i;
                r = i + mid - 1;
                break;
            }
        }
        // If we have a possible range
        // Minimize it
        if (can) {
            high = mid - 1;
        }
        else {
            low = mid + 1;
        }
    }
    // Print the range
    cout << l << " " << r;
}
 
// Driver Code
int main()
{
    // Initialize the array arr[]
    vector arr = { 1, 2, 2, 2 };
    int K = 2;
    int N = arr.size();
 
    // Function call
    find_minrange(arr, N, K);
    return 0;
}


Java
// Java program to implement
// the above approach
import java.util.*;
 
class GFG
{
 
  // Function to minimize the range
  // To divide the array arr
  // Into k subarrays that has
  // Number of elements in the range
  // Greater than out of range
  static void find_minrange(int[] arr, int n, int k)
  {
 
    // Initialize the count vector
    // To store the frequencies
    // Of the elements
    int[] count = new int[n + 1];
    for (int i = 0; i < arr.length; i++)
      count[arr[i]]++;
 
    // Initialize a vector prefix sum to
    // Store the number of elements till
    // That index
    int[] prefixsum = new int[n + 1];
 
    // Now traverse through from[1, n]
    // And store the count of elements till i
    for (int i = 1; i <= n; i++)
      prefixsum[i] = prefixsum[i - 1] + count[i];
 
    int low = 1, high = n;
 
    // Initialize l, r to store the range
    int l = 0, r = 0;
 
    while (low <= high) {
      // Initialize the mid
      int mid = (low + high) / 2;
 
      boolean can = false;
 
      // For each range size (mid)
      for (int i = 1; i <= n - mid + 1; i++) {
 
        // Count the number of elements
        // In the range [i, i+mid-1]
        // And out of the range
        int inrange = prefixsum[i + mid - 1]
          - prefixsum[i - 1];
        int outrange = n - inrange;
 
        // Check if the difference of inrange
        // And outrange is greater than
        // or equal to k
        if (inrange - outrange >= k) {
 
          // Store the range
          // Since it is a possible range
          can = true;
          l = i;
          r = i + mid - 1;
          break;
        }
      }
      // If we have a possible range
      // Minimize it
      if (can == true) {
        high = mid - 1;
      }
      else {
        low = mid + 1;
      }
    }
    // Print the range
    System.out.print(l + " " + r);
  }
 
  // Driver Code
  public static void main(String args[])
  {
 
    // Initialize the array arr[]
    int[] arr = { 1, 2, 2, 2 };
    int K = 2;
    int N = arr.length;
 
    // Function call
    find_minrange(arr, N, K);
  }
}
 
// This code is contributed by code_hunt.


Python3
# python3 code for the above approach
 
# Function to minimize the range
# To divide the array arr
# Into k subarrays that has
# Number of elements in the range
# Greater than out of range
def find_minrange(arr, n, k):
 
    # Initialize the count vector
    # To store the frequencies
    # Of the elements
    count = [0 for _ in range(n + 1)]
    for x in arr:
        count[x] += 1
 
    # Initialize a vector prefix sum to
    # Store the number of elements till
    # That index
    prefixsum = [0 for _ in range(n + 1)]
 
    # Now traverse through from[1, n]
    # And store the count of elements till i
    for i in range(1, n+1):
        prefixsum[i] = prefixsum[i - 1] + count[i]
 
    low, high = 1, n
 
    # Initialize l, r to store the range
    l, r = 0, 0
 
    while (low <= high):
        # Initialize the mid
        mid = (low + high) // 2
 
        can = False
 
        # For each range size (mid)
        for i in range(1, n - mid + 1 + 1):
 
            # Count the number of elements
            # In the range [i, i+mid-1]
            # // And out of the range
            inrange = prefixsum[i + mid - 1] - prefixsum[i - 1]
            outrange = n - inrange
 
            # Check if the difference of inrange
            # And outrange is greater than
            # or equal to k
            if (inrange - outrange >= k):
 
                # Store the range
                # Since it is a possible range
                can = True
                l = i
                r = i + mid - 1
                break
 
        # If we have a possible range
        # Minimize it
        if (can):
            high = mid - 1
 
        else:
            low = mid + 1
 
    # Print the range
    print(f"{l} {r}")
 
# Driver Code
if __name__ == "__main__":
 
    # Initialize the array arr[]
    arr = [1, 2, 2, 2]
    K = 2
    N = len(arr)
 
    # Function call
    find_minrange(arr, N, K)
 
# This code is contributed by rakeshsahni


C#
// C# code for the above approach
using System;
class GFG {
 
  // Function to minimize the range
  // To divide the array arr
  // Into k subarrays that has
  // Number of elements in the range
  // Greater than out of range
  static void find_minrange(int[] arr, int n, int k)
  {
 
    // Initialize the count vector
    // To store the frequencies
    // Of the elements
    int[] count = new int[n + 1];
    for (int i = 0; i < arr.Length; i++)
      count[arr[i]]++;
 
    // Initialize a vector prefix sum to
    // Store the number of elements till
    // That index
    int[] prefixsum = new int[n + 1];
 
    // Now traverse through from[1, n]
    // And store the count of elements till i
    for (int i = 1; i <= n; i++)
      prefixsum[i] = prefixsum[i - 1] + count[i];
 
    int low = 1, high = n;
 
    // Initialize l, r to store the range
    int l = 0, r = 0;
 
    while (low <= high) {
      // Initialize the mid
      int mid = (low + high) / 2;
 
      bool can = false;
 
      // For each range size (mid)
      for (int i = 1; i <= n - mid + 1; i++) {
 
        // Count the number of elements
        // In the range [i, i+mid-1]
        // And out of the range
        int inrange = prefixsum[i + mid - 1]
          - prefixsum[i - 1];
        int outrange = n - inrange;
 
        // Check if the difference of inrange
        // And outrange is greater than
        // or equal to k
        if (inrange - outrange >= k) {
 
          // Store the range
          // Since it is a possible range
          can = true;
          l = i;
          r = i + mid - 1;
          break;
        }
      }
      // If we have a possible range
      // Minimize it
      if (can == true) {
        high = mid - 1;
      }
      else {
        low = mid + 1;
      }
    }
    // Print the range
    Console.Write(l + " " + r);
  }
 
  // Driver Code
  public static void Main()
  {
 
    // Initialize the array arr[]
    int[] arr = { 1, 2, 2, 2 };
    int K = 2;
    int N = arr.Length;
 
    // Function call
    find_minrange(arr, N, K);
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Javascript



输出
2 2

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