1
1
/**
2
+ * 347. 前 K 个高频元素
2
3
* @param {number[] } nums
3
4
* @param {number } k
4
5
* @return {number[] }
5
6
*/
6
7
var topKFrequent = function ( nums , k ) {
7
- // 方法一: 哈希表 + 排序
8
+ // 方法一: 哈希表 + 快速排序 (nlogn)
8
9
// 时间复杂度: O(n log n)
9
10
10
11
const map = new Map ( ) ;
@@ -15,7 +16,7 @@ var topKFrequent = function (nums, k) {
15
16
16
17
// return Array.from(map).sort((a, b) => b[1] - a[1]).slice(0, k).map(item => item[0]);
17
18
18
- // 方法二: 堆( 优先队列)
19
+ // 方法二: 优先队列 (堆 )
19
20
// 时间复杂度: O(n log k)
20
21
const temp = Array . from ( map ) ;
21
22
buildMinHeap ( temp ) ;
@@ -59,3 +60,88 @@ function swap(array, i, j) {
59
60
array [ i ] = array [ j ] ;
60
61
array [ j ] = temp ;
61
62
}
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