@@ -18,64 +18,10 @@ var topKFrequent = function (nums, k) {
18
18
19
19
// 方法二: 优先队列 (堆)
20
20
// 时间复杂度: O(n log k)
21
- const temp = Array . from ( map ) ;
22
- buildMinHeap ( temp ) ;
23
-
24
- while ( temp . length > k ) {
25
- swap ( temp , 0 , temp . length - 1 ) ;
26
- temp . pop ( ) ;
27
- heapify ( temp , 0 , temp . length ) ;
28
- }
29
-
30
- return temp . map ( ( item ) => item [ 0 ] ) ;
31
- } ;
32
-
33
- function buildMinHeap ( array ) {
34
- const size = array . length ;
35
- for ( let i = size >> 1 ; i >= 0 ; i -- ) {
36
- heapify ( array , i , size ) ;
37
- }
38
- }
39
-
40
- // 堆化 (下移)
41
- function heapify ( array , index , heapSize ) {
42
- const left = 2 * index + 1 ;
43
- const right = 2 * index + 2 ;
44
- let largest = index ;
45
-
46
- if ( left < heapSize && array [ left ] [ 1 ] < array [ largest ] [ 1 ] ) {
47
- largest = left ;
48
- }
49
- if ( right < heapSize && array [ right ] [ 1 ] < array [ largest ] [ 1 ] ) {
50
- largest = right ;
51
- }
52
- if ( largest !== index ) {
53
- swap ( array , index , largest ) ;
54
- heapify ( array , largest , heapSize ) ;
55
- }
56
- }
57
-
58
- function swap ( array , i , j ) {
59
- const temp = array [ i ] ;
60
- array [ i ] = array [ j ] ;
61
- array [ j ] = temp ;
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 ] ) ;
21
+ const heap = new MinHeap ( ) ;
75
22
76
23
for ( const item of map . entries ( ) ) {
77
24
heap . push ( item ) ;
78
-
79
25
if ( heap . size ( ) > k ) {
80
26
heap . pop ( ) ;
81
27
}
@@ -89,59 +35,80 @@ function solution(nums, k) {
89
35
}
90
36
91
37
return result ;
92
- }
38
+
39
+ } ;
93
40
94
41
/**
95
42
* 优先队列 - 堆
96
43
* 对外暴露接口:
97
44
* - push: 向队尾添加元素
98
45
* - pop: 从队头取出元素
99
46
*/
100
- class PrioQueue {
101
- constructor ( compareFn ) {
102
- this . compareFn = compareFn ;
47
+ class MinHeap {
48
+ constructor ( ) {
103
49
this . queue = [ ] ;
104
50
}
105
51
106
52
push ( item ) {
107
53
if ( item ) {
108
54
this . queue . push ( item ) ;
109
- // 执行上移操作
110
- this . shiftUp ( this . size ( ) - 1 ) ;
55
+ // 上移
56
+ this . siftUp ( this . size ( ) - 1 ) ;
111
57
}
112
58
}
113
59
114
60
pop ( ) {
115
61
if ( this . size ( ) === 0 ) {
116
- return undefined ;
62
+ return ;
117
63
}
118
64
if ( this . size ( ) === 1 ) {
119
65
return this . queue . pop ( ) ;
120
66
}
121
- // 被移除值(堆顶)
122
- const removedValue = this . queue [ 0 ] ;
123
- // 弹出队列尾部的元素, 放到队头
67
+ const removedItem = this . queue [ 0 ] ;
124
68
this . queue [ 0 ] = this . queue . pop ( ) ;
125
- // 执行上移操作
126
- this . shiftUp ( 0 ) ;
69
+ // 下沉
70
+ this . siftDown ( 0 ) ;
127
71
128
- return removedValue ;
72
+ return removedItem ;
129
73
}
130
74
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 ] ;
75
+ // 上移
76
+ siftUp ( index ) {
77
+ const parent = index === 0 ? null : ( index - 1 ) >> 1 ;
136
78
137
- if ( index > 0 && this . compareFn ( currValue , parentValue ) < 0 ) {
138
- swap ( this . queue , index , parentIndex ) ;
139
- // 继续执行上移操作
140
- this . shiftUp ( parentIndex ) ;
79
+ if ( index > 0 && this . queue [ index ] [ 1 ] < this . queue [ parent ] [ 1 ] ) {
80
+ swap ( this . queue , index , parent ) ;
81
+ this . siftUp ( parent ) ;
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 last = index ;
91
+
92
+ if ( left < size && this . queue [ left ] [ 1 ] < this . queue [ last ] [ 1 ] ) {
93
+ last = left ;
94
+ }
95
+ if ( right < size && this . queue [ right ] [ 1 ] < this . queue [ last ] [ 1 ] ) {
96
+ last = right ;
97
+ }
98
+
99
+ if ( last !== index ) {
100
+ swap ( this . queue , index , last ) ;
101
+ this . siftDown ( last ) ;
141
102
}
142
103
}
143
104
144
105
size ( ) {
145
106
return this . queue . length ;
146
107
}
108
+ }
109
+
110
+ function swap ( arr , i , j ) {
111
+ const temp = arr [ i ] ;
112
+ arr [ i ] = arr [ j ] ;
113
+ arr [ j ] = temp ;
147
114
}
0 commit comments