1
+ /*
2
+ * @lc app=leetcode.cn id=347 lang=javascript
3
+ *
4
+ * [347] 前 K 个高频元素
5
+ */
6
+
7
+ // @lc code=start
8
+ /**
9
+ * @param {number[] } nums
10
+ * @param {number } k
11
+ * @return {number[] }
12
+ */
13
+ var topKFrequent = function ( nums , k ) {
14
+ const map = new Map ( ) ;
15
+
16
+ for ( let i = 0 ; i < nums . length ; i ++ ) {
17
+ const curr = nums [ i ] ;
18
+ map . set ( curr , ( map . get ( curr ) || 0 ) + 1 ) ;
19
+ }
20
+
21
+ // 优先队列 (小顶堆)
22
+ const heap = new MinHeap ( ) ;
23
+
24
+ for ( const item of map . entries ( ) ) {
25
+ heap . push ( item ) ;
26
+
27
+ if ( heap . size ( ) > k ) {
28
+ heap . pop ( ) ;
29
+ }
30
+ }
31
+
32
+ const result = [ ] ;
33
+
34
+ for ( let i = heap . size ( ) - 1 ; i >= 0 ; i -- ) {
35
+ const item = heap . pop ( ) ;
36
+ result . push ( item [ 0 ] ) ;
37
+ }
38
+
39
+ return result ;
40
+ } ;
41
+
42
+ class MinHeap {
43
+ constructor ( ) {
44
+ this . queue = [ ] ;
45
+ }
46
+
47
+ push ( item ) {
48
+ if ( item ) {
49
+ this . queue . push ( item ) ;
50
+ // 执行上移操作
51
+ this . siftUp ( this . size ( ) - 1 ) ;
52
+ }
53
+ }
54
+
55
+ pop ( ) {
56
+ if ( this . size ( ) === 0 ) {
57
+ return undefined ;
58
+ }
59
+ if ( this . size ( ) === 1 ) {
60
+ return this . queue . pop ( ) ;
61
+ }
62
+ // 被移除值(堆顶)
63
+ const removedValue = this . queue [ 0 ] ;
64
+ // 弹出队列尾部的元素, 放到队头
65
+ this . queue [ 0 ] = this . queue . pop ( ) ;
66
+ // 执行下沉操作
67
+ this . siftDown ( 0 ) ;
68
+
69
+ return removedValue ;
70
+ }
71
+
72
+ // 上移操作
73
+ siftUp ( index ) {
74
+ const parentIndex = index === 0 ? null : ( index - 1 ) >> 1 ;
75
+ const parentValue = this . queue [ parentIndex ] ;
76
+ const currValue = this . queue [ index ] ;
77
+
78
+ if ( index > 0 && currValue [ 1 ] < parentValue [ 1 ] ) {
79
+ swap ( this . queue , index , parentIndex ) ;
80
+ // 继续执行上移操作
81
+ this . siftUp ( parentIndex ) ;
82
+ }
83
+ }
84
+
85
+ // 下移
86
+ siftDown ( index ) {
87
+ const left = index * 2 + 1 ;
88
+ const right = index * 2 + 2 ;
89
+ const size = this . size ( ) ;
90
+ let largest = index ;
91
+
92
+ if ( left < size && this . queue [ left ] [ 1 ] < this . queue [ largest ] [ 1 ] ) {
93
+ largest = left ;
94
+ }
95
+ if ( right < size && this . queue [ right ] [ 1 ] < this . queue [ largest ] [ 1 ] ) {
96
+ largest = right ;
97
+ }
98
+
99
+ if ( largest !== index ) {
100
+ swap ( this . queue , index , largest ) ;
101
+ this . siftDown ( largest ) ;
102
+ }
103
+ }
104
+
105
+ size ( ) {
106
+ return this . queue . length ;
107
+ }
108
+ }
109
+
110
+ function swap ( array , i , j ) {
111
+ const temp = array [ i ] ;
112
+ array [ i ] = array [ j ] ;
113
+ array [ j ] = temp ;
114
+ }
115
+ // @lc code=end
0 commit comments