Least Number of Unique Integers after K Removals
Drop the rarest integers first — sort frequencies ascending and consume the budget.
3 min read
top-k greedy hash-map
Problem#
Remove exactly k elements from arr so the number of distinct remaining values is minimized. Return that count.
Examples#
arr = [5,5,4], k = 1→1arr = [4,3,1,1,3,3,2], k = 3→2
Constraints#
1 <= arr.length <= 10^5.
Approach#
Sort frequencies ascending. Eliminate the rarest values first — each one removed eliminates one distinct value if we cover its full count. Sum frequencies left-to-right; when the running sum exceeds k, the remaining number of frequencies is the answer.
Solution#
class Solution {public: int findLeastNumOfUniqueInts(vector<int>& arr, int k) { unordered_map<int,int> freq; for (int x : arr) ++freq[x]; vector<int> counts; for (auto& [_, c] : freq) counts.push_back(c); sort(counts.begin(), counts.end()); int removed = 0, i = 0; while (i < (int)counts.size() && removed + counts[i] <= k) { removed += counts[i++]; } return counts.size() - i; }};import "sort"
func findLeastNumOfUniqueInts(arr []int, k int) int { freq := map[int]int{} for _, x := range arr { freq[x]++ } counts := make([]int, 0, len(freq)) for _, c := range freq { counts = append(counts, c) } sort.Ints(counts) removed, i := 0, 0 for i < len(counts) && removed+counts[i] <= k { removed += counts[i] i++ } return len(counts) - i}from typing import Listfrom collections import Counter
class Solution: def findLeastNumOfUniqueInts(self, arr: List[int], k: int) -> int: counts = sorted(Counter(arr).values()) removed, i = 0, 0 while i < len(counts) and removed + counts[i] <= k: removed += counts[i] i += 1 return len(counts) - ifunction findLeastNumOfUniqueInts(arr, k) { const freq = new Map(); for (const x of arr) freq.set(x, (freq.get(x) ?? 0) + 1); const counts = [...freq.values()].sort((a, b) => a - b); let removed = 0, i = 0; while (i < counts.length && removed + counts[i] <= k) { removed += counts[i++]; } return counts.length - i;}class Solution { public int findLeastNumOfUniqueInts(int[] arr, int k) { Map<Integer, Integer> freq = new HashMap<>(); for (int x : arr) freq.merge(x, 1, Integer::sum); int[] counts = new int[freq.size()]; int idx = 0; for (int c : freq.values()) counts[idx++] = c; Arrays.sort(counts); int removed = 0, i = 0; while (i < counts.length && removed + counts[i] <= k) { removed += counts[i++]; } return counts.length - i; }}function findLeastNumOfUniqueInts(arr: number[], k: number): number { const freq = new Map<number, number>(); for (const x of arr) freq.set(x, (freq.get(x) ?? 0) + 1); const counts = [...freq.values()].sort((a, b) => a - b); let removed = 0, i = 0; while (i < counts.length && removed + counts[i] <= k) { removed += counts[i++]; } return counts.length - i;}Editorial#
Greedy is optimal: removing all occurrences of the rarest value uses the fewest of our k removals per distinct-value eliminated. Sorting frequencies and consuming left-to-right is the direct realization.
Complexity#
- Time: O(n log n).
- Space: O(n).
Concept revision#
Related#