Partition to K Equal Sum Subsets

medium backtracking bitmask

Problem

Can the array be partitioned into k non-empty subsets with equal sum?

Inputnums=[4,3,2,3,5,2,1] k=4
OutputTrue
Each subset sums to 5.

def can_partition_k_subsets(nums, k):
    s = sum(nums)
    if s % k != 0: return False
    target = s // k; nums.sort(reverse=True)
    if nums[0] > target: return False
    bucket = [0] * k
    def go(i):
        if i == len(nums): return all(b == target for b in bucket)
        seen = set()
        for j in range(k):
            if bucket[j] in seen: continue
            if bucket[j] + nums[i] > target: continue
            seen.add(bucket[j]); bucket[j] += nums[i]
            if go(i + 1): return True
            bucket[j] -= nums[i]
            if bucket[j] == 0: break
        return False
    return go(0)
function canPartitionKSubsets(nums, k) {
  const s = nums.reduce((a, b) => a + b, 0);
  if (s % k !== 0) return false;
  const target = s / k; nums.sort((a, b) => b - a);
  if (nums[0] > target) return false;
  const bucket = new Array(k).fill(0);
  const go = i => {
    if (i === nums.length) return bucket.every(b => b === target);
    const seen = new Set();
    for (let j = 0; j < k; j++) {
      if (seen.has(bucket[j])) continue;
      if (bucket[j] + nums[i] > target) continue;
      seen.add(bucket[j]); bucket[j] += nums[i];
      if (go(i + 1)) return true;
      bucket[j] -= nums[i];
      if (bucket[j] === 0) break;
    }
    return false;
  };
  return go(0);
}
boolean canPartitionKSubsets(int[] nums, int k) {
    int s = 0; for (int x : nums) s += x;
    if (s % k != 0) return false;
    int target = s / k;
    Integer[] a = Arrays.stream(nums).boxed().toArray(Integer[]::new);
    Arrays.sort(a, Comparator.reverseOrder());
    if (a[0] > target) return false;
    int[] bucket = new int[k];
    return go(a, 0, bucket, target);
}
boolean go(Integer[] a, int i, int[] bucket, int target) {
    if (i == a.length) { for (int b : bucket) if (b != target) return false; return true; }
    Set seen = new HashSet<>();
    for (int j = 0; j < bucket.length; j++) {
        if (seen.contains(bucket[j])) continue;
        if (bucket[j] + a[i] > target) continue;
        seen.add(bucket[j]); bucket[j] += a[i];
        if (go(a, i + 1, bucket, target)) return true;
        bucket[j] -= a[i];
        if (bucket[j] == 0) break;
    }
    return false;
}
bool go(vector& a, int i, vector& bucket, int target) {
    if (i == (int)a.size()) { for (int b : bucket) if (b != target) return false; return true; }
    set seen;
    for (int j = 0; j < (int)bucket.size(); j++) {
        if (seen.count(bucket[j])) continue;
        if (bucket[j] + a[i] > target) continue;
        seen.insert(bucket[j]); bucket[j] += a[i];
        if (go(a, i + 1, bucket, target)) return true;
        bucket[j] -= a[i];
        if (bucket[j] == 0) break;
    }
    return false;
}
bool canPartitionKSubsets(vector& nums, int k) {
    int s = 0; for (int x : nums) s += x;
    if (s % k != 0) return false;
    int target = s / k;
    sort(nums.begin(), nums.end(), greater());
    if (nums[0] > target) return false;
    vector bucket(k, 0);
    return go(nums, 0, bucket, target);
}
Time: O(k · 2^n) Space: O(n)