给定由N个整数和整数K组成的数组arr [] ,任务是找到具有唯一元素的相等大小的K个子集的不兼容性的最小总和。
The difference between the maximum and the minimum element in a set is known as the incompatibility of a set.
例子:
Input: arr[] = {1, 2, 1, 4}, K = 2
Output: 4
Explanation:
One of the possible ways of distributing the array into K(i.e., 2) subsets is {1, 2} and {1, 4}.
The incompatibility of the first subset = (2 – 1) = 1.
The incompatibility of the second subset = (4 – 1) = 3.
Therefore, the total sum of incompatibilities of both subsets = 1 + 3 = 4, which is the minimum among all possibilities.
Input: arr[] = {6, 3, 8, 1, 3, 1, 2, 2}, K = 4
Output: 6
Explanation:
One of the possible ways of distributing the array into K subset is: {1, 2}, {2, 3}, {6, 8}, {1, 3}.
The incompatibility of the first subset = (2-1) = 1.
The incompatibility of the second subset = (3-2) = 1.
The incompatibility of the third subset = (8-6) = 2.
The incompatibility of the fourth subset = (3-1) = 2.
Therefore, total sum of incompatibilities of K subset = 1 + 1 + 2 + 2 = 6. And it is also the minimum among all possibilities
天真的方法:最简单的方法是递归遍历给定的数组,并且在每次递归中遍历使用位掩码选择数组N / K元素的所有可能方式,并计算该子集的不兼容性,然后返回所有子集中的最小值。
时间复杂度: O(N * 2 3 * N )
辅助空间: O(N)
高效方法:可以使用动态编程来优化上述方法。可以根据以下观察结果解决给定的问题:
- 可以观察到,需要使用位屏蔽说DP(mask,i)的2状态动态编程来解决以下问题: i代表数组的当前位置,而mask的每个二进制位代表元素是否已被选择。
- 过渡状态将包括通过选择大小为N / K的子集来计算不兼容性。
- 假设X和Y是当前设置的最小值和最大值,而newmask是另一个变量,其初始值是mask
- 现在,标记所有已选定的N / K个元素中为newmask然后DP(掩模,i)由(Y只计算一次发生– X +分钟(DP(为newmask,I + 1),DP(掩模,i)的)) 。
请按照以下步骤解决问题:
- 初始化一个2D数组,例如dp [] [] 。
- 定义一个递归函数,例如dfs(mask,i) ,以计算结果:
- 基本情况:如果i> K ,则返回0 。
- 检查dp [mask] [i]!= -1 ,然后返回dp [mask] [i],因为已经计算出当前状态。
- 使用位掩码从数组中选择N / K个元素,如果可以选择仅出现一次且不属于其他子集的i个子集元素,则将当前dp状态更新为:
dp[mask][i] = min(dp[mask][i], Y – X + dfs(newmask, i))
- 返回dp [mask] [i]的值作为当前递归调用中的结果。
- 调用递归函数dfs(2 N -1,0)并打印其返回的值。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
int k;
int n;
int goal;
vector> dp;
vector bits;
// Recursive function to find
// the minimum required value
int dfs(vector A, int state,int index)
{
// Base Case
if (index >= k)
{
return 0;
}
// Stores the minimum value
// of the current state
int res = 1000;
// If dp[state][index] is
// already calculated
if (dp[state][index] != -1) {
// return dp[state][index]
return dp[state][index];
}
// Traverse over all the bits
for (int bit : bits) {
// If count of set bit is N/K
if (__builtin_popcount(bit)
== goal) {
// Store the new state after
// choosing N/K elements
int newstate = state;
// Stores the minimum and
// maximum of current subset
int mn = 100, mx = -1;
// Stores if the elements
// have been already
// selsected or not
vector visit(n+1,false);
// Stores if it is possible
// to select N/K elements
bool good = true;
// Traverse over the array
for (int j = 0; j < n; j++) {
// If not chosen already
// for another subset
if ((bit & (1 << j)) != 0) {
// If already chosen
// for another subset
// or current subset
if (visit[A[j]] == true
|| (state & (1 << j)) == 0) {
// Mark the good false
good = false;
break;
}
// Mark the current
// number visited
visit[A[j]] = true;
// Mark the current
// position in mask
// newstate
newstate = newstate
^ (1 << j);
// Update the maximum
// and minimum
mx = max(mx,
A[j]);
mn = min(mn,
A[j]);
}
}
// If good is true then
// Update the res
if (good) {
res = min(
res, mx - mn
+ dfs(A, newstate,
index + 1));
}
}
}
// Update the current sp state
dp[state][index] = res;
// Return the res
return res;
}
// Function to find the minimum
// incomatibility sum
int minimumIncompatibility(vector A, int K)
{
n = A.size();
k = K;
goal = n / k;
// Stores the count of element
map mp;
// Traverse the array
for (int i : A) {
// If number i not occurs
// in Map
if (mp.find(i)!=mp.end()){
// Put the element
// in the Map
mp[i] = 0;
}
// Increment the count of
// i in the Hash Map
mp[i]++;
// If count of i in Map is
// greater than K then
// return -1
if (mp[i] > k)
return -1;
}
// Stores all total state
int state = (1 << n) - 1;
// Travere over all the state
for (int i = 0; i <= state; i++) {
// If number of set bit
// is equal to N/K
if (__builtin_popcount(i) == goal)
bits.push_back(i);
}
// Stores the minimum value
// at a state
dp.resize(1<(k,-1));
// Intiallize the dp state
// with -1
// for (int i = 0;
// i < dp.ize(); i++) {
// Arrays.fill(dp[i], -1);
// }
// Call the recursive function
return dfs(A, state, 0);
}
// Driver code
int main()
{
vector arr = { 1, 2, 1, 4 };
int K = 2;
// Function Call
cout<<(minimumIncompatibility(arr, K));
}
// This code is contributed by mohit kumar 29.
Java
// Java program for the above approach
import java.io.*;
import java.util.*;
class Solution {
int k;
int n;
int goal;
int dp[][];
List bits = new ArrayList<>();
// Function to find the minimum
// incomatibility sum
public int minimumIncompatibility(
int[] A, int k)
{
this.n = A.length;
this.k = k;
goal = n / k;
// Stores the count of element
Map map
= new HashMap<>();
// Traverse the array
for (int i : A) {
// If number i not occurs
// in Map
if (!map.containsKey(i))
// Put the element
// in the Map
map.put(i, 0);
// Increment the count of
// i in the Hash Map
map.put(i, map.get(i) + 1);
// If count of i in Map is
// greater than K then
// return -1
if (map.get(i) > k)
return -1;
}
// Stores all total state
int state = (1 << n) - 1;
// Travere over all the state
for (int i = 0; i <= state; i++) {
// If number of set bit
// is equal to N/K
if (Integer.bitCount(i) == goal)
bits.add(i);
}
// Stores the minimum value
// at a state
dp = new int[1 << n][k];
// Intiallize the dp state
// with -1
for (int i = 0;
i < dp.length; i++) {
Arrays.fill(dp[i], -1);
}
// Call the recursive function
return dfs(A, state, 0);
}
// Recursive function to find
// the minimum required value
public int dfs(int A[], int state,
int index)
{
// Base Case
if (index >= k) {
return 0;
}
// Stores the minimum value
// of the current state
int res = 1000;
// If dp[state][index] is
// already calculated
if (dp[state][index] != -1) {
// return dp[state][index]
return dp[state][index];
}
// Traverse over all the bits
for (int bit : bits) {
// If count of set bit is N/K
if (Integer.bitCount(bit)
== goal) {
// Store the new state after
// choosing N/K elements
int newstate = state;
// Stores the minimum and
// maximum of current subset
int mn = 100, mx = -1;
// Stores if the elements
// have been already
// selsected or not
boolean visit[]
= new boolean[n + 1];
// Stores if it is possible
// to select N/K elements
boolean good = true;
// Traverse over the array
for (int j = 0; j < n; j++) {
// If not chosen already
// for another subset
if ((bit & (1 << j)) != 0) {
// If already chosen
// for another subset
// or current subset
if (visit[A[j]] == true
|| (state & (1 << j)) == 0) {
// Mark the good false
good = false;
break;
}
// Mark the current
// number visited
visit[A[j]] = true;
// Mark the current
// position in mask
// newstate
newstate = newstate
^ (1 << j);
// Update the maximum
// and minimum
mx = Math.max(mx,
A[j]);
mn = Math.min(mn,
A[j]);
}
}
// If good is true then
// Update the res
if (good) {
res = Math.min(
res, mx - mn
+ dfs(A, newstate,
index + 1));
}
}
}
// Update the current sp state
dp[state][index] = res;
// Return the res
return res;
}
}
// Driver Code
class GFG {
public static void main(String[] args)
{
Solution st = new Solution();
int[] arr = { 1, 2, 1, 4 };
int K = 2;
// Function Call
System.out.print(
st.minimumIncompatibility(arr, K));
}
}
C#
// C# program for the above approach
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
class Solution {
int k;
int n;
int goal;
int [,]dp;
List bits = new List();
// Function to find the minimum
// incomatibility sum
public int minimumIncompatibility(
int[] A, int k)
{
this.n = A.Length;
this.k = k;
goal = n / k;
// Stores the count of element
Dictionary map
= new Dictionary();
// Traverse the array
foreach(int i in A) {
// If number i not occurs
// in Map
if (!map.ContainsKey(i))
// Put the element
// in the Map
map[i]= 0;
// Increment the count of
// i in the Hash Map
map[i]++;
// If count of i in Map is
// greater than K then
// return -1
if (map[i] > k)
return -1;
}
// Stores all total state
int state = (1 << n) - 1;
// Travere over all the state
for (int i = 0; i <= state; i++) {
// If number of set bit
// is equal to N/K
if (Convert.ToString(i, 2).Count(c => c == '1') == goal)
bits.Add(i);
}
// Stores the minimum value
// at a state
dp = new int[1 << n,k];
// Intiallize the dp state
// with -1
for (int i = 0;i < dp.GetLength(0); i++) {
for (int j = 0;j < dp.GetLength(1); j++) {
dp[i,j]=-1;
}
}
// Call the recursive function
return dfs(A, state, 0);
}
// Recursive function to find
// the minimum required value
public int dfs(int []A, int state,
int index)
{
// Base Case
if (index >= k) {
return 0;
}
// Stores the minimum value
// of the current state
int res = 1000;
// If dp[state][index] is
// already calculated
if (dp[state,index] != -1) {
// return dp[state][index]
return dp[state,index];
}
// Traverse over all the bits
foreach(int bit in bits) {
// If count of set bit is N/K
if(Convert.ToString(bit, 2).Count(c => c == '1')== goal) {
// Store the new state after
// choosing N/K elements
int newstate = state;
// Stores the minimum and
// maximum of current subset
int mn = 100, mx = -1;
// Stores if the elements
// have been already
// selsected or not
bool []visit
= new bool[n + 1];
// Stores if it is possible
// to select N/K elements
bool good = true;
// Traverse over the array
for (int j = 0; j < n; j++) {
// If not chosen already
// for another subset
if ((bit & (1 << j)) != 0) {
// If already chosen
// for another subset
// or current subset
if (visit[A[j]] == true
|| (state & (1 << j)) == 0) {
// Mark the good false
good = false;
break;
}
// Mark the current
// number visited
visit[A[j]] = true;
// Mark the current
// position in mask
// newstate
newstate = newstate
^ (1 << j);
// Update the maximum
// and minimum
mx = Math.Max(mx,
A[j]);
mn = Math.Min(mn,
A[j]);
}
}
// If good is true then
// Update the res
if (good) {
res = Math.Min(
res, mx - mn
+ dfs(A, newstate,
index + 1));
}
}
}
// Update the current sp state
dp[state,index] = res;
// Return the res
return res;
}
}
// Driver Code
class GFG {
public static void Main()
{
Solution st = new Solution();
int[] arr = { 1, 2, 1, 4 };
int K = 2;
// Function Call
Console.Write(
st.minimumIncompatibility(arr, K));
}
}
// This code is contributed by rutvik_56.
4
时间复杂度: O(N 2 * 2 2 * N )
辅助空间: O(N)