Given a non-empty array of integers, return the k most frequent elements.
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
Example 2:
Input: nums = [1], k = 1
Output: [1]
Note:
- You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
- Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
方法一:利用自己的方法做了一遍;
思路:
1.用map存储数字关键字和出现的次数;
2.然后将value值存储到list当中,对它进行逆序排序;
3.通过value值的大小,找出key的值,存入到newList当中,然后返回newList
class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = computeAppearTimes(nums);
List<Integer> list = getReverseSortList(map);
List<Integer> newList = new ArrayList<Integer>();
for (int i = 0; i < k; i++) {
for (int key : map.keySet()) {
if (map.get(key) == list.get(i)) {
newList.add(key);
map.put(key, 0);
}
}
}
return newList;
}
// 将value存储到链表,并倒序排列
public List getReverseSortList(Map<Integer, Integer> map) {
List<Integer> list = new ArrayList<Integer>();
for (int i : map.keySet()) {
list.add(map.get(i));
}
Collections.sort(list);
Collections.reverse(list);
return list;
}
// 出现次数用表存储起来
private Map<Integer, Integer> computeAppearTimes(int[] arr) {
Map<Integer, Integer> map = new TreeMap();
for (int i = 0; i < arr.length; i++) {
if (!map.keySet().contains(arr[i])) {
map.put(arr[i], 1);
} else {
map.put(arr[i], map.get(arr[i]) + 1);
}
}
return map;
}
}
时间复杂度:O(log(n).n)
空间复杂度:O(n)
显然这种效率不是很高,实现起来比较容易;
我看了,答案当中有堆排序,桶排序的实现,实现思路如下:
方法二:(效率肯定比第一种高,虽然时间复杂度是一样) 利用堆和hashmap两种数据结构方式实现
class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
List<Integer> result = new ArrayList<>();
if (nums.length == 0) {
return result;
}
HashMap<Integer, Integer> map = getfreqmap(nums);
PriorityQueue<Map.Entry<Integer, Integer>> minheap = new PriorityQueue<Map.Entry<Integer, Integer>>(k, new Comparator<Map.Entry<Integer, Integer>>() {
public int compare(Map.Entry<Integer, Integer> e1, Map.Entry<Integer, Integer> e2) {
return e1.getValue().compareTo(e2.getValue());
}
});
for (Map.Entry<Integer, Integer> entry: map.entrySet()) {
if (minheap.size() < k) {
minheap.offer(entry);
} else {
if (entry.getValue() > minheap.peek().getValue()) {
minheap.poll();
minheap.offer(entry);
}
}
}
while (!minheap.isEmpty()) {
result.add(0, minheap.poll().getKey());
}
return result;
}
private HashMap<Integer, Integer> getfreqmap(int[] nums) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int num: nums) {
Integer count = map.get(num);
if (count == null) {
map.put(num, 1);
} else {
map.put(num, count + 1);
}
}
return map;
}
}
时间复杂度:O(n.log(n))
空间复杂度:O(n)
方法三:利用桶排序的思路实现
class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
List<Integer>[] bucket = new List[nums.length+1];
for (int num : nums) {
map.put(num, map.getOrDefault(num,0)+1);
}
for (int num : map.keySet()) {
int freq = map.get(num);
if (bucket[freq] == null) {
bucket[freq] = new ArrayList<Integer>();
}
bucket[freq].add(num);
}
List<Integer> res = new ArrayList<>();
for (int i = nums.length; i >= 0 && res.size() < k; i--) {
if(bucket[i] != null) {
res.addAll(bucket[i]);
}
}
return res;
}
}
时间复杂度:O(n)
空间复杂度:O(kn)