最小化范围 [L, R] 以将 Array 划分为 K 个子数组,其中大多数元素在 [L, R] 中
给定一个大小为N的数组arr[] ,任务是找到最小值范围 [L, R]使得:
- 数组可以分成K个子数组。
- [L, R] 范围内的元素大于 [l, r] 范围外的元素。
例子:
Input: arr[] = {1, 2, 2, 2}, K = 2
Output: 2 2
Explanation: [2, 2] is the range with minimum distance which can split the array into two sub-arrays as
{1, 2, 2} -> inrange = 2, outrange =1
{2} -> inrange =1, outrange = 0.
In the 2 splits number of elements inrange > outrange.
Input: arr[] = {1, 2, 3, 4}, K = 3
Output: 1 4
Explanation : [1, 4] is the range with minimum distance because the array can be splitted into 3 subarrays as
{1, 2} -> inrange = 2, outrange =1 ,
{3} -> inrange =1, outrange = 0,
{4} -> inrange = 1, outrange = 0.
In the 3 splits number of elements inrange > outrange.
朴素方法:这可以通过检查从 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)