每日一题。今天刷的是一道有关于数学的题。
题目要求
给你一个下标从 0 开始的正整数数组 nums
。
你可以对数组执行以下两种操作 任意次 :
- 从数组中选择 两个 值 相等 的元素,并将它们从数组中 删除 。
- 从数组中选择 三个 值 相等 的元素,并将它们从数组中 删除 。
请你返回使数组为空的 最少 操作次数,如果无法达成,请返回 -1
。
示例 1:
输入:nums = [2,3,3,2,2,4,2,3,4] 输出:4 解释:我们可以执行以下操作使数组为空: - 对下标为 0 和 3 的元素执行第一种操作,得到 nums = [3,3,2,4,2,3,4] 。 - 对下标为 2 和 4 的元素执行第一种操作,得到 nums = [3,3,4,3,4] 。 - 对下标为 0 ,1 和 3 的元素执行第二种操作,得到 nums = [4,4] 。 - 对下标为 0 和 1 的元素执行第一种操作,得到 nums = [] 。 至少需要 4 步操作使数组为空。
示例 2:
输入:nums = [2,1,2,2,3,3] 输出:-1 解释:无法使数组为空。
题目解析
这道题的逻辑很很简单,各种数字可以两个一删或者3个一删,求最小的删除次数。我们只需要统计出数组中各个数字的出现数量,并判断每个数字需要最少删几次即可。
对于删除来讲,肯定是一口气直接删除3个删得快,但是本题唯一的一个难点就是如何尽可能地得到最多地3。我们可以对每个数字做模除。
如果n被3整除,那么直接返回n/3即可。
如果n被3除余1,那么需要进行(n/3)-1次除3,进行2次除2.相当于(n/3)+1次
如果n被3除余2,那么需要进行n/3次除3,进行1次除2.相当于(n/3)+1次
虽然有这几种情况,但是从总体上看,都需要(n+2)/3次。
因为如果是第一种情况,n+2后不足3,因此对结果无影响。
第二种情况余1.加上2后正好再够一次除3,也无影响。
第三种情况余2,加上2后,正好可以凑齐一个3余1,除3的话也就是正好多了一次,还是(n/3)+1次,无影响。
还有最后一种情况,如果次数为1次则直接返回-1.
因此对于每个数字的数量,只需计算(n+2)/3的即可得到需要处理的次数。
代码实现
class Solution {
public int minOperations(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
int x = map.getOrDefault(nums[i],0);
map.put(nums[i],x+1);
}
int res=0;
for(int n :map.values()){
if(n==1) return -1;
res+=(n+2)/3;
}
return res;
}
}