前K个高频词汇 Top K Frequent Elements
LeetCode传送门347. Top K Frequent Elements
原题
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.
Example:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
Input: nums = [1], k = 1
Output: [1]
Constraints:
k is in the range [1, the number of unique elements in the array].
It is guaranteed that the answer is unique.
思考线
解题思路
方法一
先做一张 hashMap,记录所有整数出现的次数,然后将其转化为数组,根据sort方法降序排序,最后输入前k位结果即可
function topKFrequent(nums: number[], k: number): number[] {
const hash: Hash = {};
nums.forEach(item => {
if (!hash[item]) {
hash[item] = 1;
} else {
hash[item] += 1;
}
})
const data = Object.entries(hash);
const res = [];
data.sort((a, b) => b[1] - a[1]);
while (k--) {
res.push(data[k][0]);
}
return res;
};
方法二
看到最大的前K位或者最小的前K位之类的问题,本能告诉我,可以用大小顶堆来做。
根据题意,我们也可维护长度为K的小顶堆来解决问题。
代码如下
type Hash = {
string?: number
}
function topKFrequent(nums: number[], k: number): number[] {
const hash: Hash = {};
nums.forEach(item => {
if (!hash[item]) {
hash[item] = 1;
} else {
hash[item] += 1;
}
})
const data = Object.entries(hash);
console.log(data)
const minHeap = new Heap();
for (let i = 0; i < data.length; i++) {
if (minHeap.size() < k) {
minHeap.offer(data[i])
} else {
const top = minHeap.peek();
if (top[1] < data[i][1]) {
minHeap.data[0] = data[i];
minHeap.bubbleDown(0)
}
}
}
const res = []
while (k--) {
res.push(minHeap.poll()[0])
}
return res;
};
type dHash = [string | number, number]
class Heap {
data: dHash[]
comparator: (a: number, b: number) => boolean
constructor(data = [], comparator = (a: number, b: number) => a - b > 0) {
this.data = data;
this.comparator = comparator;
this.heapify();
}
heapify() {
if (this.size() <= 1) return;
for (let i = 1; i < this.size(); i++) {
this.bubbleUp(i);
}
}
bubbleUp(index) {
while (index > 0) {
const parent = (index - 1) >> 1;
if (this.comparator(this.data[parent][1], this.data[index][1])) {
this.swap(parent, index);
index = parent
} else {
break;
}
}
}
bubbleDown(index) {
while (index < this.size() - 1) {
const left = index * 2 + 1;
const right = index * 2 + 2;
let findIndex = index;
if (left < this.size() && this.comparator(this.data[findIndex][1], this.data[left][1])) {
findIndex = left;
}
if (right < this.size() && this.comparator(this.data[findIndex][1], this.data[right][1])) {
findIndex = right;
}
if (findIndex !== index) {
this.swap(findIndex, index);
index = findIndex;
} else {
break;
}
}
}
offer(val) {
this.data.push(val);
this.bubbleUp(this.size() - 1);
}
peek() {
return this.data[0];
}
poll() {
if (!this.size()) return null
const res = this.data.shift();
if (this.size()) {
this.data.unshift(this.data.pop());
this.bubbleDown(0)
}
return res;
}
size(): number {
return this.data.length;
}
swap(index1, index2) {
[this.data[index2], this.data[index1]] = [this.data[index1], this.data[index2]];
}
}
这就是我对本题的解法,如果有疑问或者更好的解答方式,欢迎留言互动。