Given an array of integers arr and an integer k. Find the least number of unique integers after removing exactly k elements.
Example 1:
Input: arr = [5,5,4], k = 1 Output: 1 Explanation: Remove the single 4, only 5 is left.Example 2:
Input: arr = [4,3,1,1,3,3,2], k = 3 Output: 2 Explanation: Remove 4, 2 and either one of the two 1s or three 3s. 1 and 3 will be left.
Constraints:
1 <= arr.length <= 10^51 <= arr[i] <= 10^90 <= k <= arr.lengthWhen you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach is to try out every single possible way of removing the given number of items from our collection. For each combination of removals we try, we count how many different types of numbers remain and we keep track of the smallest count we find.
Here's how the algorithm would work step-by-step:
import itertools
def least_num_of_unique_ints_brute_force(numbers_array, num_removals):
minimum_unique_count = float('inf')
array_length = len(numbers_array)
# Generate all possible combinations of indices to remove, matching the number of removals allowed.
all_removal_index_combinations = itertools.combinations(range(array_length), num_removals)
for indices_to_remove in all_removal_index_combinations:
remaining_elements = []
indices_to_remove_set = set(indices_to_remove)
for current_index in range(array_length):
# For each combination, we construct the list of elements that would remain after removal.
if current_index not in indices_to_remove_set:
remaining_elements.append(numbers_array[current_index])
# We count the unique numbers in the remaining list to see how many types are left.
unique_count_after_removal = len(set(remaining_elements))
# The goal is to find the minimum possible number of unique integers across all removal scenarios.
if unique_count_after_removal < minimum_unique_count:
minimum_unique_count = unique_count_after_removal
# If k is the length of the array, all items are removed, leaving 0 unique integers.
return minimum_unique_count if num_removals < array_length else 0To get rid of the most unique numbers, the best strategy is to remove numbers that appear the least frequently. By focusing on the rarest numbers first, we can eliminate unique values using the fewest removals possible.
Here's how the algorithm would work step-by-step:
from collections import Counter
def find_least_num_of_unique_ints(integer_array, removals_left):
if removals_left >= len(integer_array):
return 0
number_frequencies = Counter(integer_array)
# Sorting by frequency is crucial to greedily remove the least common elements first.
sorted_frequencies = sorted(number_frequencies.values())
number_of_unique_integers = len(sorted_frequencies)
for frequency_of_number in sorted_frequencies:
# We check if we can remove all occurrences of numbers with this frequency.
if removals_left >= frequency_of_number:
removals_left -= frequency_of_number
number_of_unique_integers -= 1
else:
# If we cannot remove all occurrences of this group, we can't remove any more unique numbers.
break
return number_of_unique_integers| Case | How to Handle |
|---|---|
| Input array `arr` is empty or null | The number of unique integers is zero, so the function should return 0. |
| `k` is zero, meaning no elements can be removed | The solution should simply return the initial count of unique elements in the array. |
| `k` is greater than or equal to the total number of elements in the array | All elements will be removed, so the solution should return 0 unique integers. |
| All elements in the array are identical | The logic correctly identifies one unique group, and since k is less than array length, it will not be removed, returning 1. |
| All elements in the array are unique | The solution will remove k unique elements one by one, resulting in `initial_unique_count - k` remaining integers. |
| `k` is large, but not large enough to remove all elements of any group | The greedy removal strategy handles this by reducing counts but not eliminating any unique groups, correctly returning the initial unique count. |
| The array contains negative numbers, zeros, and positive numbers | A hash map handles any integer value correctly, as they are just keys, so the logic is unaffected. |
| The input array size is very large (e.g., up to 10^5) | The O(N log N) or O(N) solution based on counting and sorting frequencies scales efficiently and avoids timeouts. |