Skip to content

Commit 0607b23

Browse files
committed
Update 347.前-k-个高频元素 (二刷)
1 parent 029b3e5 commit 0607b23

File tree

2 files changed

+46
-78
lines changed

2 files changed

+46
-78
lines changed

algorithms/top-k-frequent-elements.js

Lines changed: 44 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -18,64 +18,10 @@ var topKFrequent = function (nums, k) {
1818

1919
// 方法二: 优先队列 (堆)
2020
// 时间复杂度: 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();
7522

7623
for (const item of map.entries()) {
7724
heap.push(item);
78-
7925
if (heap.size() > k) {
8026
heap.pop();
8127
}
@@ -89,59 +35,80 @@ function solution(nums, k) {
8935
}
9036

9137
return result;
92-
}
38+
39+
};
9340

9441
/**
9542
* 优先队列 - 堆
9643
* 对外暴露接口:
9744
* - push: 向队尾添加元素
9845
* - pop: 从队头取出元素
9946
*/
100-
class PrioQueue {
101-
constructor(compareFn) {
102-
this.compareFn = compareFn;
47+
class MinHeap {
48+
constructor() {
10349
this.queue = [];
10450
}
10551

10652
push(item) {
10753
if (item) {
10854
this.queue.push(item);
109-
// 执行上移操作
110-
this.shiftUp(this.size() - 1);
55+
// 上移
56+
this.siftUp(this.size() - 1);
11157
}
11258
}
11359

11460
pop() {
11561
if (this.size() === 0) {
116-
return undefined;
62+
return;
11763
}
11864
if (this.size() === 1) {
11965
return this.queue.pop();
12066
}
121-
// 被移除值(堆顶)
122-
const removedValue = this.queue[0];
123-
// 弹出队列尾部的元素, 放到队头
67+
const removedItem = this.queue[0];
12468
this.queue[0] = this.queue.pop();
125-
// 执行上移操作
126-
this.shiftUp(0);
69+
// 下沉
70+
this.siftDown(0);
12771

128-
return removedValue;
72+
return removedItem;
12973
}
13074

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;
13678

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);
141102
}
142103
}
143104

144105
size() {
145106
return this.queue.length;
146107
}
108+
}
109+
110+
function swap(arr, i, j) {
111+
const temp = arr[i];
112+
arr[i] = arr[j];
113+
arr[j] = temp;
147114
}

vs-lt/347.前-k-个高频元素.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ var topKFrequent = function(nums, k) {
1818
map.set(curr, (map.get(curr) || 0) + 1);
1919
}
2020

21-
// 优先队列 (小顶堆)
21+
// 优先队列 (小根堆)
22+
// 时间复杂度: nlogk
2223
const heap = new MinHeap();
2324

2425
for (const item of map.entries()) {

0 commit comments

Comments
 (0)