输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
输入: nums = [1], k = 1
输出: [1]
1 )使用堆排序
class MinHeap {
heap: Record<string, any>[] = [];
// 交换节点位置
swap(i, j) {
[this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
}
// 获得父节点
getParentIndex(i) {
return (i - 1) >> 1;
}
// 获取左子节点
getLeftIndex(i) {
return (i << 1) + 1; // 极客写法
}
// 获取右子节点
getRightIndex(i) {
return (i << 1) + 2;
}
// 向上移动
shiftUp(index) {
// 如果到了堆顶元素,index是0,则不要再上移了
if(!index) return;
const parentIndex = this.getParentIndex(index)
if(this.heap[parentIndex]?.value > this.heap[index].value) {
this.swap(parentIndex, index)
this.shiftUp(parentIndex)
}
}
// 下移
shiftDown(index) {
// 边界1:如果到了堆尾元素,则不要再下移了
if(index >= this.heap.length - 1) return;
const size = this.size();
const leftIndex = this.getLeftIndex(index);
const rightIndex = this.getRightIndex(index);
if (leftIndex < size && this.heap[leftIndex]?.value < this.heap[index].value) {
this.swap(leftIndex, index);
this.shiftDown(leftIndex);
}
// 注意,这里的 this.heap[index].value 和上面重复,不能使用变量,因为上个if中存在 swap 和 shiftDown, 使用变量有可能出问题
if (rightIndex < size && this.heap[rightIndex]?.value < this.heap[index].value) {
this.swap(rightIndex, index);
this.shiftDown(rightIndex);
}
}
// 插入
insert(value) {
this.heap.push(value);
this.shiftUp(this.heap.length - 1);
}
// 删除堆顶
pop() {
// pop()方法删除数组最后一个元素并返回,赋值给堆顶
this.heap[0] = this.heap.pop();
// 对堆顶重新排序
this.shiftDown(0);
}
// 获取堆顶
peak() {
return this.heap[0];
}
// 获取堆的大小
size() {
return this.heap.length;
}
}
function topKFrequent(nums: number[], k: number): number[] {
const map = new Map();
nums.forEach(n => {
map.set(n, map.has(n)? map.get(n) + 1 : 1);
})
const h = new MinHeap();
map.forEach((value, key) => {
h.insert({value, key});
// 保证堆的尺寸是k
(h.size() > k) && h.pop();
})
return h.heap.map(a => a.key);
}
2 )使用字典
function topKFrequent(nums: number[], k: number): number[] {
const map = new Map();
nums.forEach(n => {
map.set(n, map.has(n)? map.get(n) + 1 : 1);
})
// console.log(map); // 这是一个map结构
// console.log(Array.from(map)); // 将map转换为二维数组,[[值, 频率], [值, 频率]] 这是无序的
// 对Array.from(map)产生的二维矩阵进行频率的排序
const list = Array.from(map).sort((a,b) => b[1] - a[1])
return list.slice(0, k).map(i => i[0]); // 返回按频率排序的前K个元素值
}