题目要求

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:

输入: nums = [1], k = 1
输出: [1]

提示:

  • 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
  • 你的算法的时间复杂度必须优于 O(n log n), n 是数组的大小。
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
  • 你可以按任意顺序返回答案。

实现思路

使用map实现:

最直接的实现方法就是先用map保存所有元素在数组中出现的次数。然后按照元素出现的次数对元素进行倒叙排序,最后取前k个元素即可。

该方法的时间复杂度为O(nlogn)空间复杂度为O(n)。并不满足题目的要求。

桶排序:

桶排序的工作原理就是假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。

  • 首先使用 map 来存储每个元素出现的次数
  • 然后创建一个数组(有数量的桶),将次数作为数组下标,对于出现次数不同的数字集合,存入对应的数组下标(桶内)即可。

该方法的时间复杂度:O(n)空间复杂度:O(n)

代码实现

map实现:

/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent = function(nums, k) {
let map = {}

for(let i = 0; i < nums.length; i++) {
map[nums[i]] ? map[nums[i]] += 1 : map[nums[i]] = 1
}

return Object.keys(map).sort((a, b) => map[b] - map[a]).slice(0, k)
};

桶排序:

/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent = function(nums, k) {
let map = {}

for(let i = 0; i < nums.length; i++) {
map[nums[i]] ? map[nums[i]] += 1 : map[nums[i]] = 1
}

return bucketSort(map, k)
};

// 桶排序
let bucketSort = (map, k) => {
let arr = [], res = []

for(let key in map){
if(!arr[map[key]]){
arr[map[key]] = [key]
}else{
arr[map[key]].push(key)
}
}

for(let i = arr.length - 1;i >= 0 && res.length < k;i--){
if(arr[i]) {
res.push(...arr[i])
}
}
return res
}

提交结果

map:

【LeetCode 347】前 K 个高频元素_JavaScript


桶排序:

【LeetCode 347】前 K 个高频元素_算法_02