Skip to content

Commit 029b3e5

Browse files
committed
Update
1 parent 38eca3e commit 029b3e5

File tree

1 file changed

+88
-2
lines changed

1 file changed

+88
-2
lines changed

algorithms/top-k-frequent-elements.js

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
/**
2+
* 347. 前 K 个高频元素
23
* @param {number[]} nums
34
* @param {number} k
45
* @return {number[]}
56
*/
67
var topKFrequent = function (nums, k) {
7-
// 方法一: 哈希表 + 排序
8+
// 方法一: 哈希表 + 快速排序 (nlogn)
89
// 时间复杂度: O(n log n)
910

1011
const map = new Map();
@@ -15,7 +16,7 @@ var topKFrequent = function (nums, k) {
1516

1617
// return Array.from(map).sort((a, b) => b[1] - a[1]).slice(0, k).map(item => item[0]);
1718

18-
// 方法二: 堆(优先队列)
19+
// 方法二: 优先队列 (堆)
1920
// 时间复杂度: O(n log k)
2021
const temp = Array.from(map);
2122
buildMinHeap(temp);
@@ -59,3 +60,88 @@ function swap(array, i, j) {
5960
array[i] = array[j];
6061
array[j] = temp;
6162
}
63+
64+
65+
function solution(nums, k) {
66+
const map = new Map();
67+
68+
for (let i = 0; i < nums.length; i++) {
69+
const curr = nums[i];
70+
map.set(curr, (map.get(curr) || 0) + 1);
71+
}
72+
73+
// 小顶堆
74+
const heap = new PrioQueue((a, b) => a[1] - b[1]);
75+
76+
for (const item of map.entries()) {
77+
heap.push(item);
78+
79+
if (heap.size() > k) {
80+
heap.pop();
81+
}
82+
}
83+
84+
const result = [];
85+
86+
for (let i = heap.size() - 1; i >= 0; i--) {
87+
const item = heap.pop();
88+
result.push(item[0]);
89+
}
90+
91+
return result;
92+
}
93+
94+
/**
95+
* 优先队列 - 堆
96+
* 对外暴露接口:
97+
* - push: 向队尾添加元素
98+
* - pop: 从队头取出元素
99+
*/
100+
class PrioQueue {
101+
constructor(compareFn) {
102+
this.compareFn = compareFn;
103+
this.queue = [];
104+
}
105+
106+
push(item) {
107+
if (item) {
108+
this.queue.push(item);
109+
// 执行上移操作
110+
this.shiftUp(this.size() - 1);
111+
}
112+
}
113+
114+
pop() {
115+
if (this.size() === 0) {
116+
return undefined;
117+
}
118+
if (this.size() === 1) {
119+
return this.queue.pop();
120+
}
121+
// 被移除值(堆顶)
122+
const removedValue = this.queue[0];
123+
// 弹出队列尾部的元素, 放到队头
124+
this.queue[0] = this.queue.pop();
125+
// 执行上移操作
126+
this.shiftUp(0);
127+
128+
return removedValue;
129+
}
130+
131+
// 上移操作
132+
shiftUp(index) {
133+
const parentIndex = index === 0 ? null : (index - 1) >> 1;
134+
const parentValue = this.queue[parentIndex];
135+
const currValue = this.queue[index];
136+
137+
if (index > 0 && this.compareFn(currValue, parentValue) < 0) {
138+
swap(this.queue, index, parentIndex);
139+
// 继续执行上移操作
140+
this.shiftUp(parentIndex);
141+
}
142+
}
143+
144+
size() {
145+
return this.queue.length;
146+
}
147+
}

0 commit comments

Comments
 (0)