- 问题描述
给你一个整数数组
arr。你可以从中选出一个整数集合,并删除这些整数在数组中的每次出现。返回 至少 能删除数组中的一半整数的整数集合的最小大小。
- 示例
输入:arr = [3,3,3,3,5,5,5,2,2,7]
输出:2
解释:选择 {3,7} 使得结果数组为 [5,5,5,2,2]、长度为 5(原数组长度的一半)。
大小为 2 的可行集合有 {3,5},{3,2},{5,2}。
选择 {2,7} 是不可行的,它的结果数组为 [3,3,3,3,5,5,5],新数组长度大于原数组的二分之一。
输入:arr = [7,7,7,7,7,7]
输出:1
解释:我们只能选择集合 {7},结果数组为空。
输入:arr = [1,9]
输出:1
输入:arr = [1000,1000,3,7]
输出:1
输入:arr = [1,2,3,4,5,6,7,8,9,10]
输出:5
- 提示
1 <= arr.length <= 10^5
arr.length为偶数
1 <= arr[i] <= 10^5
- 解读
一、先统计每个数字的个数,存到数组里 A。 原来数组总长度一半为 S
二、再看这些数组里 A 的子数组的的有没有刚好等于S,如果没有,再看有没有超过一些的。这些循环。
三、按照二的想法,这是一个 0-1 背包问题。 注意到一点, 数组 A 的总个数是一定, 即为2S。 也即是说,不会有这种现象,存在一个子数组,长度超过S。 同时也存在一个子数组,长度 = S。
四、按三的分析,这个最用贪心就可以解决,先把A 从大到小排序 ,遍历累加个数,直到刚好超过 S ,那这个子数组个数就是题意要求的个数
- 代码
public int minSetSize(int[] arr) {
int[] nums = new int[Arrays.stream(arr).summaryStatistics().getMax() + 1];
Arrays.fill(nums, 0);
int len = arr.length / 2;
for (int i = 0; i < arr.length; i++) {
nums[arr[i]]++;
}
// 求nums 里面,有没有和为 len 的
Arrays.sort(nums);
int p = 0;
int t = 0;
for (int i = nums.length - 1; i >= 0; i--) {
p = p + nums[i];
t++;
if (p >= len) {
break;
}
}
return t;
}
本文探讨了一个特定的算法问题:如何选择一个整数集合以删除数组中至少一半的元素,同时使集合大小最小。通过统计数组中各元素出现次数并采用贪心算法进行优化,最终实现了高效解决方案。
801

被折叠的 条评论
为什么被折叠?



