CMD Guide
HomeDSAAdvanced Patterns

medium Least Number of Unique Integers after K Removals

Problem Statement

Given an array of integers arr and an integer k, return the least number of unique integers remaining after removing exactly k elements from the array.

Examples

Example 1

Example 2

Example 3

Constraints:

Try it yourself

Try solving this question here:

🎯 STRICT STANDOUT — Least Number of Unique Integers after K Removals — problem

1. Why / judgment

Greedy on frequencies: to minimize distinct remaining, spend removals on smallest frequencies first (eliminate whole keys cheaply). This is counting + sort-of-buckets, not “remove largest keys”. Counter-intuition trap: removing from the most frequent key barely reduces distinct count.

2. Big-O derivation (K11)

n≤1e5.
Count map O(n).
Sort frequencies O(k log k) k=distinct, or bucket counts of counts O(n).
Then scan ascending freqs subtracting from k until k insufficient.
Total O(n log n) sort or O(n) bucket.

3. Pattern + when-NOT (K12)

Name: FREQ MAP + REMOVE RAREST (BUCKET/GREEDY)

Recognition: exactly k deletions; minimize distinct survivors.

When-NOT: Maximize distinct remaining → opposite greedy (trim from largest). Removals of whole types with costs → different knapsack. k=0 → answer = distinct now.

4. Edge hand-run (K13)

arr=[5,5,4,3,2,3,2,3,3,2] k=6 → can eliminate 4(1)+5(2)+2(3)=6 → left only 3 → 1.
k≥n → 0 unique.
Already unique and k=1 → n−1.

5. Interviewer follow-ups (model answers)

Q1. Why rarest first?
A: Eliminating a key of freq f costs f removals and reduces distinct by 1; any other spend of f removals reduces distinct by at most 1, and smaller f maximizes keys killed per removal budget.

Q2. Heap of frequencies?
A: Works O(n + k log d) but bucket of counts is linear when freqs ≤ n.

Q3. HashMap vs counting sort on values?
A: Values up to 1e9 → must HashMap for first histogram; second structure is on frequencies (≤n).

6. Short drills

Drill: [7,7,7,8,8,9] k=2 → 2.
Drill: k=0 always returns number of distinct.
✅ Solution Least Number of Unique Integers after K Removals

Problem Statement

Given an array of integers arr and an integer k, return the least number of unique integers remaining after removing exactly k elements from the array.

Examples

Example 1

  • Input: arr = [5, 5, 4, 3, 2, 3, 2, 3, 3, 2], k = 6
  • Expected Output: 1
  • Justification: After removing 4, all 5, and three instances of 2, the updated array will be [3, 3, 3, 3]. It will have only 1 unique element.

Example 2

  • Input: arr = [7, 7, 7, 8, 8, 9], k = 2
  • Expected Output: 2
  • Justification: Removing two instances of the 8, or 1 instance of 8 and 1 of 9, there will be 2 unique elements in the array.

Example 3

  • Input: arr = [1, 2, 2, 3, 4, 3], k = 4
  • Expected Output: 1
  • Justification: You can remove 1, 4 and either both instances of 2 or 3, and the final array will be [2, 2] or [3, 3], based on which element you have removed from the array.

Constraints:

  • 1 <= arr.length <= 105
  • 1 <= arr[i] <= 109
  • 0 <= k <= arr.length

Solution

To solve this problem, the approach involves tracking the frequency of each integer in the array and then removing the least frequent elements first. This strategy ensures that we maximize the reduction in the number of unique integers. By removing the least frequent elements, we effectively minimize the unique elements left in the array.

The reasoning behind this approach is that removing the least frequent elements impacts the count of unique integers more significantly. This most effective solution ensures that the remaining elements are as few as possible.

Step-by-step Algorithm

  1. Frequency Mapping:

    • Initialize an empty hash map elementFrequency to store the frequency of each element.
    • Iterate through each element in arr.
    • For each element, update the count in elementFrequency map.
  2. Frequency Counting:

    • Initialize an array frequencyCount of size n + 1 (where n is the length of arr) to count the total occurrences of each frequency.
    • Iterate through the values in elementFrequency map.
    • For each frequency value, increment the corresponding index in frequencyCount array.
  3. Initialize Unique Elements Count:

    • Set uniqueElements to the size of the elementFrequency map (number of unique keys), storing total number of unique elements in the given array.
  4. Remove Elements:

    • Iterate through possible frequencies from 1 to n.
    • For each frequency i:
      • Calculate elementsToRemove as the minimum of k // i and frequencyCount[i]. Here, k//i is the maximum number of elements we can remove which has frequency equal to i with the remaining k value, and frequencyCount[i] is actual number of elements we can remove, which has a frequency equal to i. for example, if we have 3 elements with frequency 2, and remaining k is 4, we can remove only 2 elements with frequency 2.
      • Decrease k by i * elementsToRemove.
      • Decrease uniqueElements by elementsToRemove.
      • If k becomes less than i, break the loop and return uniqueElements as we can't remove more elements.
  5. Return Result:

    • If all elements are processed, return uniqueElements.

Algorithm Walkthrough

Let's use the Input arr = [5, 5, 4, 3, 2, 3, 2, 3, 3, 2] and k = 6

  1. Frequency Mapping:

    • Initialize elementFrequency as {}.
    • Iterate through arr:
      • Add 5: elementFrequency becomes {5: 1}.
      • Add 5: elementFrequency becomes {5: 2}.
      • Add 4: elementFrequency becomes {5: 2, 4: 1}.
      • Add 3: elementFrequency becomes {5: 2, 4: 1, 3: 1}.
      • Add 2: elementFrequency becomes {5: 2, 4: 1, 3: 1, 2: 1}.
      • Add 3: elementFrequency becomes {5: 2, 4: 1, 3: 2, 2: 1}.
      • Add 2: elementFrequency becomes {5: 2, 4: 1, 3: 2, 2: 2}.
      • Add 3: elementFrequency becomes {5: 2, 4: 1, 3: 3, 2: 2}.
      • Add 3: elementFrequency becomes {5: 2, 4: 1, 3: 4, 2: 2}.
      • Add 2: elementFrequency becomes {5: 2, 4: 1, 3: 4, 2: 3}.
  2. Frequency Counting:

    • Initialize frequencyCount as [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].
    • Iterate through values in elementFrequency:
      • Frequency of 5: increment frequencyCount[2] to 1.
      • Frequency of 4: increment frequencyCount[1] to 1.
      • Frequency of 3: increment frequencyCount[4] to 1.
      • Frequency of 2: increment frequencyCount[3] to 1.
    • frequencyCount becomes [0, 1, 2, 1, 1, 0, 0, 0, 0, 0, 0].
  3. Initialize Unique Elements Count:

    • uniqueElements is set to the size of elementFrequency which is 4.
  4. Remove Elements:

    • Iterate through frequencies from 1 to n:
      • Frequency 1:
        • elementsToRemove = min(6 // 1, 1) = 1.
        • k is decreased by 1 * 1 = 1, so k becomes 5.
        • uniqueElements is decreased by 1, so uniqueElements becomes 3.
      • Frequency 2:
        • elementsToRemove = min(5 // 2, 1) = 1.
        • k is decreased by 1 * 2 = 2, so k becomes 3.
        • uniqueElements is decreased by 1, so uniqueElements becomes 2.
      • Frequency 3:
        • elementsToRemove = min(3 // 2, 1) = 1.
        • k is decreased by 1 * 3 = 3, so k becomes 0.
        • uniqueElements is decreased by 1, so uniqueElements becomes 1.
        • Now, K < 3. So, stop iterations, and return uniqueElements.
  5. Final Result:

    • The number of least unique elements is uniqueElements, which is 1.

Code

java
import java.util.*;

public class Solution {

  public int reduceUniqueInts(int[] arr, int k) {
    // Step 1: Count the frequency of each element
    Map<Integer, Integer> elementFrequency = new HashMap<>();
    for (int num : arr) {
      elementFrequency.put(num, elementFrequency.getOrDefault(num, 0) + 1);
    }

    int n = arr.length;

    // Step 2: Array to count how many elements have a certain frequency
    int[] frequencyCount = new int[n + 1];

    // Step 3: Fill the frequencyCount array based on elementFrequency map
    for (int freq : elementFrequency.values()) {
      frequencyCount[freq]++;
    }

    // Total unique elements
    int uniqueElements = elementFrequency.size();

    // Step 4: Iterate through possible frequencies and remove elements
    for (int i = 1; i <= n; i++) {
      int elementsToRemove = Math.min(k / i, frequencyCount[i]);
      k -= (i * elementsToRemove);
      uniqueElements -= elementsToRemove;

      if (k < i) {
        return uniqueElements;
      }
    }

    return 0;
  }

  public static void main(String[] args) {
    Solution reducer = new Solution();
    System.out.println(
      reducer.reduceUniqueInts(new int[] { 5, 5, 4, 3, 2, 3, 2, 3, 3, 2 }, 6)
    ); // Output: 1
    System.out.println(
      reducer.reduceUniqueInts(new int[] { 7, 7, 7, 8, 8, 9 }, 2)
    ); // Output: 2
    System.out.println(
      reducer.reduceUniqueInts(new int[] { 1, 2, 2, 3, 4, 3 }, 4)
    ); // Output: 1
  }
}

Complexity Analysis

Time Complexity

  1. We traverse the array arr once to populate the elementFrequency map, which takes time, where n is the array length.
  2. We then traverse the elementFrequency map to populate the frequencyCount array. Since the map can have at most n entries, this step also takes time.
  3. Finally, we traverse the frequencyCount array, which has a size of n + 1, making this step as well.

Combining all these steps, the overall time complexity is .

Space Complexity

  1. We create a elementFrequency map that can have a maximum of n entries.
  2. We also create a frequencyCount array with a size of n + 1.

Hence, the total space complexity is .

🎯 STRICT STANDOUT — Solution Least Number of Unique Integers after K Removals

1. Why / judgment

After histogram, sort the list of frequencies ascending. For each f: if k≥f, k-=f and unique--; else break. Remaining unique is the answer. Bucket alternative: cntFreq[f] = how many keys have frequency f; scan f=1..n.

2. Big-O derivation (K11)

[5,5,4,3,2,3,2,3,3,2] freqs: 5→2,4→1,3→4,2→3 → sorted [1,2,3,4]
k=6: kill 1 →k5 unique3; kill 2 →k3 unique2; kill 3 →k0 unique1 → answer 1 ✓
[7,7,7,8,8,9] freqs [1,2,3] k=2 → kill 1, then 1 of the 2 → cannot kill second fully → uniques left 2 ✓

3. Pattern + when-NOT (K12)

Name: ASCENDING FREQ ELIMINATION

Recognition: budgeted deletions minimize cardinality of support.

When-NOT: Online stream with unknown k → different; here k known offline.

4. Edge hand-run (K13)

All equal length n, k=n-1 → still 1 unique.
k=n → 0.
One each distinct, k=n//2 → n−k.

5. Interviewer follow-ups (model answers)

Q1. Is sorting frequencies O(n log n) necessary?
A: No — bucket by frequency value in O(n) since each freq ∈ [1,n].

Q2. Proof rarest optimal?
A: Exchange: if you partially spent on a heavy key while a lighter full key remains, reassign those removals to finish the lighter key — distinct drops more or equal.

Q3. What if k removes only part of a freq?
A: Stops mid-key; that key still counts as one unique — algorithm correctly breaks without unique--.

6. Short drills

Drill: [1,2,2,3,4,3] k=4 → 1.
Drill: implement bucket O(n) version.
🧩 Pattern · Hashing

Recognize it: Membership / frequency / “have I seen this?” in O(1) → a hash map or set.

▶ Visualize this problem (step it, predict each fork)
⛶ Open this problem debugger in explore mode
🤖 Don't fully get this? Learn it with Claude

Stuck on Least Number of Unique Integers after K Removals? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🪜 Hint ladder (no spoilers)

Progressively stronger hints — you still solve it.

I'm working on the problem **Least Number of Unique Integers after K Removals** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🎨 Explain the approach visually

See the technique, not just code.

Explain the optimal approach to **Least Number of Unique Integers after K Removals** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔍 Review my solution

Catch bugs, edge cases, sub-optimality.

I'll paste my solution to **Least Number of Unique Integers after K Removals**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔁 Drill the pattern

Lock in recognition with look-alikes.

Give me 2 problems that use the SAME underlying pattern as **Least Number of Unique Integers after K Removals**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes