-
Notifications
You must be signed in to change notification settings - Fork 71
/
No347.top-k-frequent-elements.js
145 lines (126 loc) · 3.27 KB
/
No347.top-k-frequent-elements.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* Difficulty:
* Medium
*
* Desc:
* Given a non-empty array of integers, return the k most frequent elements.
*
* Example:
* Given [1,1,1,2,2,3] and k = 2, return [1,2].
*
* Note:
* You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
* Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
*
* 给定一个非空的整数数组,返回其中出现频率前 k 高的元素
*/
/*
* =============================== Solution 1 ===============================
* 最大堆
*/
const exchange = (arr, index1, index2) => {
const tmp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = tmp;
};
class Heap {
constructor(arr, frequentMap) {
this.frequentMap = frequentMap;
this.heap = [...arr];
for (let i = this.heap.length - 1; i >= 0; i -= 1) {
// 每一个元素作为父元素,和其子元素进行比较
this.sortWithChild(i + 1);
}
}
more(fatherPos, childPos) {
return this.frequentMap.get(this.heap[fatherPos - 1]) < this.frequentMap.get(this.heap[childPos - 1]);
}
sortWithChild(pos) {
const childPos1 = pos * 2;
const childPos2 = pos * 2 + 1;
if (childPos1 > this.heap.length) return;
if (this.more(pos, childPos1)) {
exchange(this.heap, pos - 1, childPos1 - 1);
}
if (childPos2 > this.heap.length) return;
if (this.more(pos, childPos2)) {
exchange(this.heap, pos - 1, childPos2 - 1);
}
this.sortWithChild(childPos1);
this.sortWithChild(childPos2);
}
dequeue() {
exchange(this.heap, 0, this.heap.length - 1);
const result = this.heap.pop();
this.sortWithChild(1);
return result;
}
}
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent_1 = function(nums, k) {
const frequentMap = new Map();
for (let i = 0; i < nums.length; i += 1) {
const num = nums[i];
const frequent = frequentMap.get(num) !== undefined
? frequentMap.get(num) + 1
: 1;
frequentMap.set(num, frequent);
}
const keys = frequentMap.keys();
const heap = new Heap(keys, frequentMap);
const result = [];
for (let i = 1; i <= k; i += 1) {
result.push(heap.dequeue())
}
return result;
};
/*
* =============================== Solution 2 ===============================
* 快排分区
*/
const partition = (nums, i, j) => {
const target = i
const base = nums[target]
while (i < j) {
while (i < j && nums[j][1] <= base[1]) j -= 1
while (i < j && nums[i][1] >= base[1]) i += 1
if (i >= j) break
const tmp = nums[i]
nums[i] = nums[j]
nums[j] = tmp
}
nums[target] = nums[i]
nums[i] = base
return i
}
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent_2 = function(nums, k) {
const dict = nums.reduce((map, num) => {
map[num] = (map[num] || 0) + 1
return map
}, {})
const list = Object.entries(dict)
let i = 0
let j = list.length - 1
while (i < j) {
const mid = partition(list, i, j)
if (mid === k) break
if (mid < k) {
i = mid + 1
} else {
j = mid - 1
}
}
return list.slice(0, k).map(p => Number(p[0]))
}
// Test Case
// topKFrequent([1,1,1,2,2,3], 2) => [1, 2]
// topKFrequent([5,-3,9,1,7,7,9,10,2,2,10,10,3,-1,3,7,-9,-1,3,3], 3) => [3, 7, 10]