You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
class Solution {
public int[] topKFrequent(int[] nums, int k) {
int n = nums.length;
int[] res = new int[k];
int i = 0, j = 0;
HashMap<Integer, Integer> map = new HashMap();
// (nums, times) put into map
for (i = 0; i < n; ++i) {
if (!map.containsKey(nums[i]))
map.put(nums[i], 1);
else {
int t = map.get(nums[i]);
map.replace(nums[i], t + 1);
}
}
// initalize array res
HashSet<Integer> kNums = new HashSet();
for (i = 0; i < n && j < k; ++i) {
if (!kNums.contains(nums[i])) {
kNums.add(nums[i]);
// res[j++] = nums[i];
heapInsert(res, nums[i], map, j);
++j;
}
}
// min heap
for (; i < n; ++i) {
if (!kNums.contains(nums[i]) && map.get(nums[i]) > map.get(res[0])) {
kNums.add(nums[i]);
res[0] = nums[i];
heapify(res, 0, k, map);
}
}
return res;
}
public void heapInsert(int[] heap, int value,
HashMap<Integer, Integer> map, int index) {
heap[index] = value;
while (index != 0) {
int parent = (index - 1) / 2;
if (map.get(heap[parent]) > map.get(heap[index])) {
int t = heap[parent];
heap[parent] = heap[index];
heap[index] = t;
index = parent;
}
else break;
}
}
public void heapify(int[] heap, int index, int k, HashMap<Integer, Integer> map) {
int left = index * 2 + 1, right = index * 2 + 2;
int smallest = index;
while (left < k) {
if (map.get(heap[left]) < map.get(heap[index]))
smallest = left;
if (right < k && map.get(heap[smallest]) > map.get(heap[right]))
smallest = right;
if (smallest != index) {
int t = heap[smallest];
heap[smallest] = heap[index];
heap[index] = t;
}else {
break;
}
index = smallest;
left = index * 2 + 1;
right = index * 2 + 2;
}
}
}
class Solution {
public int[] topKFrequent(int[] nums, int k) {
//check input
if(nums == null || nums.length == 0 || k < 1) return new int[1];
//HashMap to count frequency of the elements
//Key as number and values as frequency or counts
Map<Integer, Integer> map = new HashMap<>();
//count number of frequencies for given array
for(int num: nums) {
map.put(num, map.getOrDefault(num,0) + 1);
}
//priority Queue(Max heap) to with custome comparator (Descending order)
Queue <Integer> queue = new PriorityQueue<>((e1,e2) -> map.get(e2) - map.get(e1));
//Add all elements(which will sort via their frequency or counts)
queue.addAll(map.keySet());
int[] result = new int[k];
int i = 0;
while(!queue.isEmpty()) {
result[i++] = queue.poll();
if(i==k) break;
}
return result;
}
}
这段代码里有很多我没见过的并且很有意思的写法:
map.getOrDefault(Object key, V defaultValue)方法官方讲解是"Returns the value to which the specified key is mapped, or defaultValue if this map contains no mapping for the key.",即如果Map中有Key,则返回配对的Value,否则返回参数defalutValue,而加上map.put()方法,意味着如果Map中有Key,则取出Value然后加一再更新(put方法有更新的作用:"If the map previously contained a mapping for the key, the old value is replaced"),如果没有Key,则将(Key, 1)加入Map中。
new PriorityQueue<>((e1,e2) -> map.get(e2) - map.get(e1)),这里设计如何定义Map的键值对的构造器,有三种写法,可以看参考资料3。这里不同的是,Queue的类型是Integer类的,加入了Map来实现compare方法,并不是常规的Map.Entry<>。
Given a non-empty array of integers, return the k most frequent elements.
Example 1:
Example 2:
Note:
题目要求的是返回前K个经常出现的数,是求前K个最大的数的升级版(书上的例题)。
这类问题可以创建一个最小(大)堆,达到O(nlogn)的时间复杂度。我们可以利用HashMap保存数组中元素和它出现次数的映射,作为比较关系,建立堆。
当然还可以使用Java集合类中的优先队列PriorityQueue,实际上就是最大(小)堆。
我卡在了如何定义构造器创建合适的优先队列,然后看了如下大佬的做法:
这段代码里有很多我没见过的并且很有意思的写法:
2020/09/09:我又来重写了一遍:
既然可以用优先队列,那也可以使用TreeMap,TreeMap的按键排序简单,但按值排序需要将其转化为list,再使用Collection.sort进行排序:
这段代码有两个Map,TreeMap和LinkedHashMap,因为Collections.sort排好序后TreeMap顺序仍然不变,所以需要将排好序的list中元素放进LinkedHashMap中确保排好序。LinkedHashMap的优点在于,它不同于HashMap根据HashCode值存储数据,它保持了插入顺序,但同时速度慢,相应知识可以查看参考资料5。这样平均运行时间增大了很多,所以还不如用PriorityQueue。
还有一种方法是利用桶排序的方法,详细做法可以看下方参考资料6。
参考资料:
The text was updated successfully, but these errors were encountered: