[LeetCode] 1338. Reduce Array Size to The Half
You are given an integer array arr. You can choose a set of integers and remove all the occurrences of these integers in the array.
Return the minimum size of the set so that at least half of the integers of the array are removed.
Example 1:
Input: arr = [3,3,3,3,5,5,5,2,2,7]
Output: 2
Explanation: Choosing {3,7} will make the new array [5,5,5,2,2] which has size 5 (i.e equal to half of the size of the old array).
Possible sets of size 2 are {3,5},{3,2},{5,2}.
Choosing set {2,7} is not possible as it will make the new array [3,3,3,3,5,5,5] which has a size greater than half of the size of the old array.
Example 2:
Input: arr = [7,7,7,7,7,7]
Output: 1
Explanation: The only possible set you can choose is {7}. This will make the new array empty.
Constraints:
2 <= arr.length <= 105
arr.length is even.
1 <= arr[i] <= 105
数组大小减半。
给你一个整数数组 arr。你可以从中选出一个整数集合,并删除这些整数在数组中的每次出现。返回 至少 能删除数组中的一半整数的整数集合的最小大小。
思路一 - counting sort
首先我们看一下数组中出现的最大元素是什么,记录为 max。之后我们创建一个长度为 max + 1 的数组 count,记录所有元素的出现次数,并在记录完毕之后对其排序。当这个 count 数组有序之后,我们从元素最大的地方开始统计,计算一下每个元素的出现次数,当统计到数组中一半整数为止。
复杂度
时间O(nlogn)
空间O(n)
代码
Java实现
class Solution {
public int minSetSize(int[] arr) {
int max = Integer.MIN_VALUE;
for (int num : arr) {
max = Math.max(max, num);
}
int[] count = new int[max + 1];
for (int num : arr) {
count[num]++;
}
Arrays.sort(count);
int half = arr.length / 2;
int res = 0;
for (int i = count.length - 1; i >= 0; i--) {
half -= count[i];
res++;
if (half <= 0) {
return res;
}
}
return arr.length;
}
}
思路二 - 最大堆
既然是试图删除数组中的一些 unique 的元素,使得删除的元素数量尽量大,但是这个集合尽量小,那么我们就需要统计每个元素在 input 数组中的出现次数。这里我们用 hashmap 统计,统计好的结果我们存入一个以 priority queue 表示的最大堆,堆顶是出现次数最多的数字。这样每次堆顶元素弹出的时候,他的出现次数是当前最多的,这样才能尽快地删除数组中一半整数。
复杂度
时间O(nlogn)
空间O(n)
代码
Java实现
class Solution {
public int minSetSize(int[] arr) {
HashMap<Integer, Integer> map = new HashMap<>();
int n = arr.length;
for (int num : arr) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
// [key, value]
PriorityQueue<int[]> queue = new PriorityQueue<>((a, b) -> b[1] - a[1]);
for (int num : map.keySet()) {
int val = map.get(num);
queue.offer(new int[] { num, val });
}
int res = 0;
int count = 0;
while (count < n / 2) {
count += queue.poll()[1];
res++;
}
return res;
}
}