给定一个由N 个整数组成的数组 arr[] ,任务是将数组拆分为最少数量的不相交组,使得组中任何一对元素之间的差异等于它们在该组中的位置之间的差异。
例子:
Input: arr[] = {30, 32, 44, 31, 45, 32, 31, 33}
Output: 3
Explanation:
The one possible possible way to split the array is:
- First group: {30, 31, 32, 33}
- Second group: {31, 32}
- Third group: {44, 45}
Therefore, the number of groups is 3, which is the minimum number of groups in which the array can be split satisfying the conditions.
Input: arr[] = {1, 5, 3, 1, 7, 7, 9}
Output: 7
朴素的方法:最简单的方法是,对于每个小于或等于N 的整数 K ,将数组拆分为 K 个子集,然后检查数组的所有子集是否满足给定条件。如果发现是真的,则打印可能的分区的最小大小。
时间复杂度: O(N (N + 2) )
辅助空间: O(N)
高效的方法:上述方法可以基于观察到每个组中的元素必须排序并且相邻元素之间的差异应为1 进行优化。请按照以下步骤解决问题:
- 按升序对给定数组进行排序。
- 初始化一个 Map,比如mp来存储数组元素的频率。
- 初始化一个变量,比如count为0来存储形成的不相交组的最小数量的计数。
- 遍历给定的数组arr[] ,并增加映射 mp中每个元素的频率。
- 使用变量i遍历给定数组arr[] ,并执行以下步骤:
- 如果ARR [I]的在地图MP计数为至少1,和的计(ARR [I] – 1)在地图MP则:
- 将 count的值增加1 。
- 迭代直到mp中 arr[i]的计数大于0并且在每次迭代中,将mp[arr[i]]减 1并将arr[i]增加1 。
- 如果ARR [I]的在地图MP计数为至少1,和的计(ARR [I] – 1)在地图MP则:
- 最后,完成以上步骤后,打印count的值作为答案。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to split the array into
// minimum number of disjoint groups
// satisying the conditions
int numberOfSplit(int arr[], int N)
{
// Sort the array in ascending order
sort(arr, arr + N);
// Stores frequency of array elements
unordered_map mp;
// Traverse the array, arr[]
for (int i = 0; i < N; i++)
mp[arr[i]]++;
// Stores the number of groups
int count = 0;
// Traverse the array, arr[]
for (int i = 0; i < N; i++) {
// If mp[arr[i]] is at least 1
// and mp[arr[i]-1] is 0
if (mp[arr[i]] > 0 && mp[arr[i] - 1] == 0) {
// Increment the count by 1
count++;
// Iterate until mp[arr[i]]
// is greater than 0
while (mp[arr[i]] != 0) {
// Decrement mp[arr[i]]
// by 1
mp[arr[i]]--;
// Increment arr[i] by 1
arr[i]++;
}
}
}
// Return the resultant count
return count;
}
// Driver Code
int main()
{
int arr[] = { 30, 32, 44, 31, 45, 32, 31, 33 };
int N = sizeof(arr) / sizeof(arr[0]);
cout << numberOfSplit(arr, N);
return 0;
}
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
// Function to split the array into
// minimum number of disjoint groups
// satisying the conditions
static int numberOfSplit(int []arr, int N)
{
// Sort the array in ascending order
Array.Sort(arr);
// Stores frequency of array elements
Dictionary mp = new Dictionary();
// Traverse the array, arr[]
for(int i = 0; i < N; i++)
{
if (mp.ContainsKey(arr[i]))
mp[arr[i]] += 1;
else
mp.Add(arr[i], 0);
}
// Stores the number of groups
int count = 2;
// Traverse the array, arr[]
for(int i = 0; i < N; i++)
{
// If mp[arr[i]] is at least 1
// and mp[arr[i]-1] is 0
if (mp[arr[i]] > 0 && mp[arr[i] - 1] == 0)
{
// Increment the count by 1
count++;
// Iterate until mp[arr[i]]
// is greater than 0
while (mp[arr[i]] != 0)
{
// Decrement mp[arr[i]]
// by 1
mp[arr[i]]--;
// Increment arr[i] by 1
arr[i]++;
}
}
}
// Return the resultant count
return count;
}
// Driver Code
public static void Main()
{
int []arr = { 30, 32, 44, 31,
45, 32, 31, 33 };
int N = arr.Length;
Console.Write(numberOfSplit(arr, N));
}
}
// This code is contributed by SURENDRA_GANGWAR
3
时间复杂度: O(N*log N)
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。