1338.数组大小减半

【LetMeFly】1338.数组大小减半:贪心(有限删除出现次数多的)+哈希表

力扣题目链接:https://leetcode.cn/problems/reduce-array-size-to-the-half/

给你一个整数数组 arr。你可以从中选出一个整数集合,并删除这些整数在数组中的每次出现。

返回 至少 能删除数组中的一半整数的整数集合的最小大小。

 

示例 1:

输入: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],新数组长度大于原数组的二分之一。

示例 2:

输入:arr = [7,7,7,7,7,7]
输出:1
解释:我们只能选择集合 {7},结果数组为空。

 

提示:

  • 1 <= arr.length <= 105
  • arr.length 为偶数
  • 1 <= arr[i] <= 105

解题方法:贪心 + 哈希表

当然是优先删除出现次数多的元素。怎么统计每个元素出现了多少次?使用一个哈希表即可。

之后对“每个出现次数”组成的数组排序,从出现次数最大的开始累加,直到和不小于$\frac{arr}{2}$为止,所累加的数目即为答案。

  • 时间复杂度$O(n\log n)$,其中$n=len(arr)$
  • 空间复杂度$O(n)$

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
int minSetSize(vector<int>& arr) {
unordered_map<int, int> ma;
for (int t : arr) {
ma[t]++;
}
vector<int> times;
for (auto&& [_, t] : ma) {
times.push_back(t);
}
sort(times.begin(), times.end());
int ans = 0;
for (int cnt = 0, i = times.size() - 1; cnt < arr.size() / 2; ans++, i--) {
cnt += times[i];
}
return ans;
}
};

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from typing import List
from collections import Counter

class Solution:
def minSetSize(self, arr: List[int]) -> int:
ma = Counter(arr)
times = [t for i, t in ma.items()]
times.sort()
ans, cnt, i = 0, 0, len(times) - 1
while cnt < len(arr) // 2:
ans += 1
cnt += times[i]
i -= 1
return ans

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;

class Solution {
public int minSetSize(int[] arr) {
Map<Integer, Integer> ma = new HashMap<>();
for (int t : arr) {
ma.merge(t, 1, Integer::sum);
}
List<Integer> times = new ArrayList<>(ma.values());
times.sort((a, b) -> b - a);
int ans = 0;
for (int cnt = 0, i = 0; cnt < arr.length / 2; ans++, i++) {
cnt += times.get(i);
}
return ans;
}
}

Go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import "sort"

func minSetSize(arr []int) (ans int) {
ma := map[int]int{}
for _, t := range arr {
ma[t]++
}
var times []int
for _, t := range ma {
times = append(times, t)
}
sort.Slice(times, func(i, j int) bool {
return times[i] > times[j]
})
for cnt := 0; cnt < len(arr) / 2; ans++ {
cnt += times[ans]
}
return
}

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

Tisfy:https://letmefly.blog.csdn.net/article/details/144487651


1338.数组大小减半
https://blog.letmefly.xyz/2024/12/15/LeetCode 1338.数组大小减半/
作者
Tisfy
发布于
2024年12月15日
许可协议