给定一个由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)
高效的方法:上述方法可以使用动态规划进行优化。可以根据以下观察解决给定的问题:
- 可以观察到,它需要一个带有 Bitmasking 的 2 状态动态规划,比如DP(mask, i)来解决i表示数组的当前位置,而掩码的每个二进制位表示该元素是否已经被选中的问题.
- 过渡状态将包括通过选择大小为N/K的子集来计算不兼容性。
- 假设X和Y是当前集合的最小值和最大值,并且newmask是另一个变量,其初始值为掩码
- 现在,标记所有已选择的N/ K 个元素在newmask 中只出现一次,然后DP(mask, i)由(Y – X + min(DP(newmask, i + 1), DP(mask, i) )) 。
请按照以下步骤解决问题:
- 初始化一个二维数组,比如dp[][] 。
- 定义一个递归函数,比如dfs (mask, i)来计算结果:
- 基本情况:如果i > K ,则返回0 。
- 检查是否dp[mask][i] != -1 ,然后返回dp[mask][i]因为 tthe current state 已经计算。
- 使用位掩码从数组中选择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)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live