欢迎关注我的刷题专栏 zhangyixing1007/leetcode
给你一个整数数组 arr 和一个整数 k 。现需要从数组中恰好移除 k 个元素,请找出移除后数组中不同整数的最少数目。
示例 1:
输入:arr = [5,5,4], k = 1 输出:1 解释:移除 1 个 4 ,数组中只剩下 5 一种整数。
示例 2:输入:arr = [4,3,1,1,3,3,2], k = 3 输出:2 解释:先移除 4、2 ,然后再移除两个 1 中的任意 1
个或者三个 3 中的任意 1 个,最后剩下 1 和 3 两种整数。提示:
1 <= arr.length <= 10^5
1 <= arr[i] <= 10^9
0 <= k <= arr.length来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/least-number-of-unique-integers-after-k-removals
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
基本思路
- 特殊输入值筛选,空啊零啊超范围啊。
- HashMap记录每一个数字出现的次数。
- 只有尽可能多地删去数字种类,留下的数字种类才会少,所以要先删出现次数最少的那些数字。这里对出现次数排序是必不可少的,但是排序不需要带上原数字。因为如果是2,3都出现三次,k=3,最后删去2或者3都无所谓,反正都只留下一个数字。并且也不需要对所有的数字排序,因为k<arr.length。所以,我们用PriorityQueue实现就好了。
- 用poll()的形式表示删除数字,返回值时不要忘记讨论 最后一个poll对应的数字是删除完毕还是删了一半的情况。
class Solution {
public int findLeastNumOfUniqueInts(int[] arr, int k) {
//特殊输入值处理
if(arr==null||arr.length==0||arr.length<=k) return 0;
if(arr.length-1==k) return 1;
//建立HashMap储存 用来arr[i]值和值出现的次数
Map<Integer, Integer> map=new HashMap<>();
for(int a:arr) map.put(a, map.getOrDefault(a, 0)+1);
PriorityQueue<Integer> pq=new PriorityQueue<>(map.values());
//然后原本的key就不重要了
//它们在原数组中出现了几次才是关键
//因为我们并不关心留下的具体是哪些数字
//我们只关心留下的数字有几种
while(k>0) k-=pq.poll();
//这里不需要考虑pq为空会报错
//因为只有arr.length<=k时pq才会为空
//但这种情况一开始就被排除了
return k==0? pq.size():pq.size()+1;
//k==0时返回 pq.size(),不解释
//k!=0时,只能是k<0
//说明最后一个poll的数还有一部分不在被删去的k个之内
//所以要+1
}
}
一些API解释
- map.getOrDefault(a,0);//如果map.keySet()中存在a就返回a的value,否则返回0。
- map.put(a, map.getOrDefault(a, 0)+1);//如果a已经存过,那么重复次数+1;如果没有那么第一次put,重复次数为1
- map.values();//返回map中所有键值对的“值”,这里类型为Collection
- PriorityQueue默认返回最小值