题目描述
给你一个下标从 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
解释:无法使数组为空。
提示:
2 <= nums.length <= 105
1 <= nums[i] <= 106
解法
方法一:哈希表 + 贪心
我们用一个哈希表 $count$ 统计数组中每个元素出现的次数,然后遍历哈希表,对于每个元素 $x$,如果 $x$ 出现的次数为 $c$,那么我们可以进行 $\lfloor \frac{c+2}{3} \rfloor$ 次操作,将 $x$ 删除,最后我们返回所有元素的操作次数之和即可。
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。
| class Solution:
def minOperations(self, nums: List[int]) -> int:
count = Counter(nums)
ans = 0
for c in count.values():
if c == 1:
return -1
ans += (c + 2) // 3
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | class Solution {
public int minOperations(int[] nums) {
Map<Integer, Integer> count = new HashMap<>();
for (int num : nums) {
// count.put(num, count.getOrDefault(num, 0) + 1);
count.merge(num, 1, Integer::sum);
}
int ans = 0;
for (int c : count.values()) {
if (c < 2) {
return -1;
}
int r = c % 3;
int d = c / 3;
switch (r) {
case (0) -> {
ans += d;
}
default -> {
ans += d + 1;
}
}
}
return ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | class Solution {
public:
int minOperations(vector<int>& nums) {
unordered_map<int, int> count;
for (int num : nums) {
++count[num];
}
int ans = 0;
for (auto& [_, c] : count) {
if (c < 2) {
return -1;
}
ans += (c + 2) / 3;
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | func minOperations(nums []int) (ans int) {
count := map[int]int{}
for _, num := range nums {
count[num]++
}
for _, c := range count {
if c < 2 {
return -1
}
ans += (c + 2) / 3
}
return
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | function minOperations(nums: number[]): number {
const count: Map<number, number> = new Map();
for (const num of nums) {
count.set(num, (count.get(num) ?? 0) + 1);
}
let ans = 0;
for (const [_, c] of count) {
if (c < 2) {
return -1;
}
ans += ((c + 2) / 3) | 0;
}
return ans;
}
|