Problem: Minimum Incompatibility

You are given an integer array `nums`​​​ and an integer `k`. You are asked to
distribute this array into `k` subsets of equal size such that there are no
two equal elements in the same subset.

A subset's incompatibility is the difference between the maximum and minimum
elements in that array.

Return the minimum possible sum of incompatibilities of the `k` subsets after
distributing the array optimally, or return `-1` if it is not possible.

A subset is a group integers that appear in the array with no particular
order.


Python solution:
import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def __init__(self):
    self.kMaxNum = 16

  def minimumIncompatibility(self, nums: List[int], k: int) -> int:
    kMaxCompatibility = (16 - 1) * (16 // 2)
    n = len(nums)
    subsetSize = n // k
    maxMask = 1 << n
    incompatibilities = self._getIncompatibilities(nums, subsetSize)

    dp = [kMaxCompatibility] * maxMask
    dp[0] = 0

    for mask in range(1, maxMask):
      if mask.bit_count() % subsetSize != 0:
        continue
      submask = mask
      while submask > 0:
        if incompatibilities[submask] != -1:
          dp[mask] = min(dp[mask], dp[mask - submask] + incompatibilities[submask])
        submask = (submask - 1) & mask

    if dp[-1] != kMaxCompatibility:
      return dp[-1]
    else:
      return -1

  def _getIncompatibilities(self, nums: List[int], subsetSize: int) -> List[int]:
    maxMask = 1 << len(nums)
    incompatibilities = [-1] * maxMask
    for mask in range(maxMask):
      if mask.bit_count() == subsetSize and self._isUnique(nums, mask, subsetSize):
        incompatibilities[mask] = self._getIncompatibility(nums, mask)
    return incompatibilities

  def _isUnique(self, nums: List[int], mask: int, subsetSize: int) -> bool:
    used = 0
    for i, num in enumerate(nums):
      if mask >> i & 1:
        used |= 1 << num
    return used.bit_count() == subsetSize

  def _getIncompatibility(self, nums: List[int], mask: int) -> int:
    mini = self.kMaxNum
    maxi = 0
    for i, num in enumerate(nums):
      if mask >> i & 1:
        maxi = max(maxi, num)
        mini = min(mini, num)
    return maxi - mini


Java solution:
class Solution {
  public int minimumIncompatibility(int[] nums, int k) {
    final int MAX_COMPATIBILITY = (16 - 1) * (16 / 2);
    final int n = nums.length;
    final int subsetSize = n / k;
    final int maxMask = 1 << n;
    final int[] incompatibilities = getIncompatibilities(nums, subsetSize);
    // dp[i] := the minimum possible sum of incompatibilities of the subset
    // of numbers represented by the bitmask i
    int[] dp = new int[maxMask];
    Arrays.fill(dp, MAX_COMPATIBILITY);
    dp[0] = 0;

    for (int mask = 1; mask < maxMask; ++mask) {
      // The number of 1s in `mask` isn't a multiple of `subsetSize`.
      if (Integer.bitCount(mask) % subsetSize != 0)
        continue;
      // https://cp-algorithms.com/algebra/all-submasks.html
      for (int submask = mask; submask > 0; submask = (submask - 1) & mask)
        if (incompatibilities[submask] != -1) // valid submask
          dp[mask] = Math.min(dp[mask], dp[mask - submask] + incompatibilities[submask]);
    }

    return dp[maxMask - 1] == MAX_COMPATIBILITY ? -1 : dp[maxMask - 1];
  }

  private static final int MAX_NUM = 16;

  // Returns an incompatibilities array where
  // * incompatibilities[i] := the incompatibility of the subset of numbers
  //   represented by the bitmask i
  // * incompatibilities[i] := -1 if the number of 1s in the bitmask i is not
  //   `subsetSize`
  private int[] getIncompatibilities(int[] nums, int subsetSize) {
    final int maxMask = 1 << nums.length;
    int[] incompatibilities = new int[maxMask];
    Arrays.fill(incompatibilities, -1);
    for (int mask = 0; mask < maxMask; ++mask)
      if (Integer.bitCount(mask) == subsetSize && isUnique(nums, mask, subsetSize))
        incompatibilities[mask] = getIncompatibility(nums, mask);
    return incompatibilities;
  }

  // Returns true if the numbers selected by `mask` are unique.
  //
  // e.g. If we call isUnique(0b1010, 2, [1, 2, 1, 4]), `used` variable
  // will be 0b1, which only has one 1 (less than `subsetSize`). In this case,
  // we should return false.
  private boolean isUnique(int[] nums, int mask, int subsetSize) {
    int used = 0;
    for (int i = 0; i < nums.length; ++i)
      if ((mask >> i & 1) == 1)
        used |= 1 << nums[i];
    return Integer.bitCount(used) == subsetSize;
  }

  // Returns the incompatibility of the selected numbers represented by the
  // `mask`.
  private int getIncompatibility(int[] nums, int mask) {
    int mn = MAX_NUM;
    int mx = 0;
    for (int i = 0; i < nums.length; ++i)
      if ((mask >> i & 1) == 1) {
        mx = Math.max(mx, nums[i]);
        mn = Math.min(mn, nums[i]);
      }
    return mx - mn;
  }
}


C++ solution:
class Solution {
 public:
  int minimumIncompatibility(vector<int>& nums, int k) {
    constexpr int kMaxCompatibility = (16 - 1) * (16 / 2);
    const int n = nums.size();
    const int subsetSize = n / k;
    const int maxMask = 1 << n;
    const vector<int> incompatibilities =
        getIncompatibilities(nums, subsetSize);
    // dp[i] := the minimum possible sum of incompatibilities of the subset
    // of numbers represented by the bitmask i
    vector<int> dp(maxMask, kMaxCompatibility);
    dp[0] = 0;

    for (unsigned mask = 1; mask < maxMask; ++mask) {
      // The number of 1s in `mask` isn't a multiple of `subsetSize`.
      if (popcount(mask) % subsetSize != 0)
        continue;
      // https://cp-algorithms.com/algebra/all-submasks.html
      for (int submask = mask; submask > 0; submask = (submask - 1) & mask)
        if (incompatibilities[submask] != -1)  // valid subset
          dp[mask] =
              min(dp[mask], dp[mask - submask] + incompatibilities[submask]);
    }

    return dp.back() == kMaxCompatibility ? -1 : dp.back();
  }

 private:
  static constexpr int kMaxNum = 16;

  // Returns an incompatibilities array where
  // * incompatibilities[i] := the incompatibility of the subset of numbers
  //   represented by the bitmask i
  // * incompatibilities[i] := -1 if the number of 1s in the bitmask i is not
  //   `subsetSize`
  vector<int> getIncompatibilities(const vector<int>& nums, int subsetSize) {
    const int maxMask = 1 << nums.size();
    vector<int> incompatibilities(maxMask, -1);
    for (unsigned mask = 0; mask < maxMask; ++mask)
      if (popcount(mask) == subsetSize && isUnique(nums, mask, subsetSize))
        incompatibilities[mask] = getIncompatibility(nums, mask);
    return incompatibilities;
  }

  // Returns true if the numbers selected by `mask` are unique.
  //
  // e.g. If we call isUnique(0b1010, 2, [1, 2, 1, 4]), `used` variable
  // will be 0b1, which only has one 1 (less than `subsetSize`). In this case,
  // we should return false.
  bool isUnique(const vector<int>& nums, int mask, int subsetSize) {
    unsigned used = 0;
    for (int i = 0; i < nums.size(); ++i)
      if (mask >> i & 1)
        used |= 1 << nums[i];
    return popcount(used) == subsetSize;
  }

  // Returns the incompatibility of the selected numbers represented by the
  // `mask`.
  int getIncompatibility(const vector<int>& nums, int mask) {
    int mn = kMaxNum;
    int mx = 0;
    for (int i = 0; i < nums.size(); ++i)
      if (mask >> i & 1) {
        mx = max(mx, nums[i]);
        mn = min(mn, nums[i]);
      }
    return mx - mn;
  }
};