Minimum Number of Operations to Make Array Empty

medium hash table counting greedy

Problem

You are given an array nums of positive integers. Repeatedly you may delete two elements with equal values, or three elements with equal values. Return the minimum number of operations to empty the array, or -1 if it is impossible.

Elements of different values never interact, so each distinct value is solved on its own. If a value appears with frequency f, the fewest deletions to clear it is ⌈f / 3⌉ (greedily use as many 3-groups as possible, filling the remainder with 2-groups). A value that appears exactly once can never be removed, making the whole task impossible.

Inputnums = [2,3,3,2,2,4,2,3,4]
Output4
Counts: 2→4, 3→3, 4→2. Ops = ⌈4/3⌉ + ⌈3/3⌉ + ⌈2/3⌉ = 2 + 1 + 1 = 4.

def minOperations(nums):
    count = {}                       # value -> frequency
    for v in nums:
        count[v] = count.get(v, 0) + 1
    ops = 0
    for f in count.values():
        if f == 1:
            return -1                # a lone value can never be paired
        ops += (f + 2) // 3          # ceil(f / 3): greedy 3s, fill with 2s
    return ops
function minOperations(nums) {
  const count = new Map();           // value -> frequency
  for (const v of nums) count.set(v, (count.get(v) || 0) + 1);
  let ops = 0;
  for (const f of count.values()) {
    if (f === 1) return -1;          // a lone value can never be paired
    ops += Math.floor((f + 2) / 3);  // ceil(f / 3): greedy 3s, fill with 2s
  }
  return ops;
}
int minOperations(int[] nums) {
    Map<Integer, Integer> count = new HashMap<>();   // value -> frequency
    for (int v : nums) count.merge(v, 1, Integer::sum);
    int ops = 0;
    for (int f : count.values()) {
        if (f == 1) return -1;       // a lone value can never be paired
        ops += (f + 2) / 3;          // ceil(f / 3): greedy 3s, fill with 2s
    }
    return ops;
}
int minOperations(vector<int>& nums) {
    unordered_map<int, int> count;   // value -> frequency
    for (int v : nums) count[v]++;
    int ops = 0;
    for (auto& [v, f] : count) {
        if (f == 1) return -1;       // a lone value can never be paired
        ops += (f + 2) / 3;          // ceil(f / 3): greedy 3s, fill with 2s
    }
    return ops;
}
Time: O(n) Space: O(k) distinct values