[路飞]_每天刷leetcode_39(前K个高频词汇 Top K Frequent Elements)

158 阅读2分钟

前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:

1<=nums.length<=1051 <= nums.length <= 10^5

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]];
    }
}

这就是我对本题的解法,如果有疑问或者更好的解答方式,欢迎留言互动。