Problem Walkthrough

Min Ops Array Empty LeetCode 2870 Guide

Count element frequencies, return -1 if any frequency is 1, and sum ceil(freq/3) per unique value — the greedy ceiling division gives the fewest remove-2-or-3 operations to empty the array.

7 min read|

Min Ops Array Empty

LeetCode 2870

Problem Overview — Remove Groups of 2 or 3 Equal Elements

LeetCode 2870 gives you an array of integers. In one operation you can remove exactly 2 or exactly 3 elements that are all equal in value. Your goal is to find the minimum number of operations to empty the entire array, or return -1 if it is impossible.

The constraint is that every removal must consist of equal elements — you cannot mix different values in one operation. This means each value in the array is independent: you can figure out the minimum operations for each value separately, then sum them up. The problem reduces to: for each unique value, how many remove-2-or-3 operations does it take to eliminate all occurrences?

Brute force tries all ways to partition each frequency into 2s and 3s, which is slow. The key insight is a greedy formula: ceil(freq/3) always gives the minimum number of groups. The only impossible case is when a value appears exactly once — you cannot form a group of 2 or 3 from a single element.

  • Input: integer array nums, e.g., [2,3,3,2,2,4,2,3,4]
  • Output: minimum operations to empty array, or -1 if impossible
  • Each operation: remove exactly 2 or 3 elements of the same value
  • A value with frequency 1 makes it impossible — return -1
  • Each unique value is independent — solve separately, then sum
  • Goal: minimize total number of remove operations across all values

Same Math as Min Rounds — LeetCode 2244 in Disguise

LeetCode 2870 is mathematically identical to LeetCode 2244 (Minimum Rounds to Complete Tasks). In 2244, you complete tasks in rounds of 2 or 3, and want to minimize rounds. Here, you remove elements in groups of 2 or 3, and want to minimize operations. The structure is the same: partition a frequency into 2s and 3s to minimize the number of groups.

In both problems, frequency 1 is impossible — you cannot form a group of 2 or 3. Any frequency of 2 or more can be decomposed into groups of 2 and 3. The answer for each frequency is ceil(freq/3). If you solved 2244 before, you can apply the same logic here with confidence.

The key insight is that 2 and 3 are the building blocks. Every integer >= 2 can be written as a combination of 2s and 3s. The greedy strategy always prefers groups of 3 (fewer operations), then uses a group of 2 to handle remainders. This greedy preference is exactly what ceil(freq/3) computes.

💡

Recognized Pattern

If you solved Min Rounds to Complete Tasks (LeetCode 2244), this is the same problem with different framing: count frequencies, check for 1s, sum ceil(freq/3). The formula and logic transfer directly — no new insight required.

Why ceil(freq/3) — The Three Remainder Cases

To minimize the number of operations, you want to use as many groups of 3 as possible (since 3 removes more elements per operation than 2). The ceiling formula ceil(freq/3) encodes the optimal grouping for all three possible remainders when dividing freq by 3.

When freq % 3 == 0, you use exactly freq/3 groups of 3, no groups of 2 needed. When freq % 3 == 1, you cannot simply take (freq-1)/3 groups of 3 with one leftover (since 1 is impossible), so instead you take (freq-4)/3 groups of 3 and 2 groups of 2, totaling (freq-4)/3 + 2 = ceil(freq/3). When freq % 3 == 2, you take (freq-2)/3 groups of 3 and 1 group of 2, totaling (freq-2)/3 + 1 = ceil(freq/3).

In all three cases, the answer is ceil(freq/3). This is why the formula works universally — it automatically handles the tricky freq % 3 == 1 case by shifting one group of 3 into two groups of 2, which costs one extra operation but eliminates the impossible leftover of 1.

  1. 1freq % 3 == 0: use freq/3 groups of 3 → ceil(freq/3) = freq/3 operations
  2. 2freq % 3 == 1: use (freq-4)/3 groups of 3 + 2 groups of 2 → ceil(freq/3) operations
  3. 3freq % 3 == 2: use (freq-2)/3 groups of 3 + 1 group of 2 → ceil(freq/3) operations
  4. 4All cases: answer per value = ceil(freq/3) = (freq + 2) // 3 in integer arithmetic
  5. 5Sum ceil(freq/3) over all unique values for the total answer

Why Frequency 1 Is Impossible — The Only Dead End

If any value appears exactly once, there is no valid operation to remove it. Every operation requires exactly 2 or exactly 3 equal elements. A lone element cannot be grouped with any other element (they must be equal), so it is stuck in the array forever. The problem requires emptying the entire array, so return -1.

Frequency 1 is the only impossible case. For every frequency >= 2, you can always decompose into groups of 2 and 3. Frequency 2 uses one group of 2. Frequency 3 uses one group of 3. Frequency 4 uses two groups of 2. Frequency 5 uses one group of 3 and one group of 2. Every higher frequency follows the same pattern.

This is guaranteed by the fact that 2 and 3 are coprime and their combinations generate all integers >= 2. You never need to check frequencies of 4, 5, or above for impossibility — only frequency 1 is a dead end. As soon as you find a count of 1 in your frequency map, you can immediately return -1 without processing other values.

ℹ️

Why Only Frequency 1 Fails

This is the only impossible case: any frequency >= 2 is achievable because 2 and 3 generate all integers >= 2 (by the Chicken McNugget theorem, every integer >= 2 can be expressed as 2a + 3b for non-negative integers a, b). Only 1 cannot be decomposed.

Walk-Through Example — [2,3,3,2,2,4,2,3,4]

Count frequencies: value 2 appears 4 times, value 3 appears 3 times, value 4 appears 2 times. No frequency equals 1, so we proceed. Apply ceil(freq/3) to each: ceil(4/3) = 2 operations for value 2 (one group of 3 + one group of 2, or two groups of 2), ceil(3/3) = 1 operation for value 3 (one group of 3), ceil(2/3) = 1 operation for value 4 (one group of 2).

Total operations = 2 + 1 + 1 = 4. This matches the expected output. The groupings are: remove [2,2,2] (1 op), remove [2] — wait, groups of 2: remove [2,2] (1 op); remove [3,3,3] (1 op); remove [4,4] (1 op). That is 4 operations total, verified.

Notice that for value 2 with freq=4, we could use two groups of 2 (2 ops) or one group of 3 plus one group of 2 (still 2 ops) — both give 2 operations. ceil(4/3) = ceil(1.33) = 2, which matches. The formula correctly identifies the minimum regardless of how you split the groups.

  1. 1Count: {2: 4, 3: 3, 4: 2} — no frequency is 1, proceed
  2. 2Value 2 (freq=4): ceil(4/3) = 2 operations → [2,2,2] + [2] or [2,2] + [2,2]
  3. 3Value 3 (freq=3): ceil(3/3) = 1 operation → [3,3,3]
  4. 4Value 4 (freq=2): ceil(2/3) = 1 operation → [4,4]
  5. 5Total = 2 + 1 + 1 = 4 operations

Code Walkthrough — Python and Java

The Python implementation uses Counter to build the frequency map in O(n). Then iterate over counts: if any count == 1, return -1. Otherwise accumulate (count + 2) // 3 (integer ceiling division). Return the total. Time O(n), space O(n) for the frequency map. The Counter import and one-pass sum make this concise — the entire solution fits in five lines.

The Java implementation uses a HashMap<Integer, Integer> to count frequencies. Iterate over the array to populate it, then iterate over values(). For each count == 1, return -1. Otherwise add (count + 2) / 3 to the result (Java integer division truncates, so adding 2 before dividing implements ceiling). Return result at the end. Same O(n) time and O(n) space.

Edge cases: all elements the same — single frequency, apply formula directly. Empty array — trivially 0 operations (no frequencies to process). Array where every element is unique — every frequency is 1, return -1 immediately. Array of pairs — every frequency is 2, each contributes 1 operation, answer = number of unique values.

⚠️

Use Integer Ceiling, Not float

Use (count + 2) // 3 not math.ceil(count / 3): integer ceiling avoids floating-point imprecision for large counts. In Python, count / 3 is float division and math.ceil works, but (count + 2) // 3 is cleaner, faster, and always exact.

Ready to master algorithm patterns?

YeetCode flashcards help you build pattern recognition through active recall and spaced repetition.

Start practicing now