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 27 28 29 30 31 32 33 34 35
| class Solution { public int minSetSize(int[] arr) { Map<Integer, Integer> numCount = new HashMap<>(); int maxCount = 0; for (int num : arr) { numCount.put(num, numCount.getOrDefault(num, 0) + 1); maxCount = Math.max(maxCount, numCount.get(num)); } List<List<Integer>> bucket = new ArrayList<>(); for (int i = 0; i <= maxCount; i++) { bucket.add(new ArrayList<>()); } for (Map.Entry<Integer, Integer> entry : numCount.entrySet()) { int num = entry.getKey(); int count = entry.getValue(); bucket.get(count).add(num); } int remain = arr.length; int removedCount = 0; for (int i = bucket.size() - 1; i >= 0; i--) { for (int num : bucket.get(i)) { if (remain > arr.length / 2) { removedCount += 1; remain -= i; } else { break; } } if (remain <= arr.length / 2) { break; } } return removedCount; } }
|
bucket sort.
时间复杂度: O(n)
空间复杂度: O(n) 创建了map, 以及list, list还装了buckets.
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 27 28 29 30 31 32 33 34
| class Solution { private static class Pair { int num; int count;
Pair(int _num, int _count) { num = _num; count = _count; } }
public int minSetSize(int[] arr) { Map<Integer, Pair> numCount = new HashMap<>(); for (int i = 0; i < arr.length; i++) { numCount.putIfAbsent(arr[i], new Pair(arr[i], 0)); numCount.get(arr[i]).count += 1; } List<Pair> list = new ArrayList<>(); for (Map.Entry<Integer, Pair> entry : numCount.entrySet()) { list.add(entry.getValue()); } Collections.sort(list, (a, b) -> b.count - a.count); int remain = arr.length, removed = 0; for (int i = 0; i < list.size(); i++) { if (remain > arr.length / 2) { remain -= list.get(i).count; removed += 1; } else { break; } } return removed; } }
|
这个时间稍微快一点儿. 就是先统计每个num的freq, 做成pair. 放到list中sort一下. 然后从大到小开始踢人. 踢到满足题意为止.
时间复杂度: O(nlogn) sort + 遍历
空间复杂度: O(n) 用map和list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Solution { public int minSetSize(int[] arr) { Map<Integer, Integer> numCount = new HashMap<>(); for (int i = 0; i < arr.length; i++) { numCount.put(arr[i], numCount.getOrDefault(arr[i], 0) + 1); } PriorityQueue<Map.Entry<Integer, Integer>> q = new PriorityQueue<>((a, b) -> b.getValue() - a.getValue()); for (Map.Entry<Integer, Integer> entry : numCount.entrySet()) { q.offer(entry); } int remain = arr.length, removed = 0; for (int i = 0; i < q.size(); i++) { if (remain > arr.length / 2) { remain -= q.poll().getValue(); removed += 1; } else { break; } } return removed; } }
|
Priority Queue来去装Map的entry而不是list再sort.
时间复杂度: O(nlogn) 遍历数组获得每个num的频率(O(n)) + 把所有的entry push进queue(O(log1 + log2 + log3….数学公式是nlogn)) + poll出来(nlogn). 因此最后就是O(nlogn)
空间复杂度: O(n)
证明:
https://math.stackexchange.com/questions/482860/how-to-calc-log1-log2-log3-log4-log-n