题目
题目来源:力扣(LeetCode)
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
方法一:快速排序
我们可以使用基于快速排序的方法,求出「出现次数数组」的前 k 大的值。
- 首先用哈希表记录每个数字出现的次数
- 对每个数及对应次数通过快排进行排序,返回前k个
- 在对数组 arr[l…r] 做快速排序的过程中,我们首先将数组划分为两个部分 arr[i…q−1] 与 [q+1…j],并使得 arr[i…q−1] 中的每一个值都不超过 arr[q],且 arr[q+1…j] 中的每一个值都大于arr[q]。
于是,我们根据 k 与左侧子数组 arr[i…q−1] 的长度(为q−i)的大小关系:
- 如果 k≤q−i,则数组 arr[l…r] 前 k 大的值,就等于子数组 arr[i…q−1] 前 k 大的值。
- 否则,数组arr[l…r] 前 k 大的值,就等于左侧子数组全部元素,加上右侧子数组 arr[q+1…j] 中前 k−(q−i) 大的值。
/*** @param {number[]} nums* @param {number} k* @return {number[]}*/var topKFrequent = function (nums, k) {// 统计出现次数const map = {};for (const n of nums) {n in map || (map[n] = 0);map[n]++;}const list = Object.entries(map);quickSelect(list, k, 0, list.length - 1, function (item, pivot) {return item[1] >= pivot[1];});return list.slice(0, k).map(el => el[0]);};/*** 把 arr[r] 当成是 pivot* 把大于等于 pivot 的数字放到左边* 把小于 pivot 的数字放到右边* @param {number[]} arr* @param {number} l* @param {number} r*/function partition(arr, l, r, comparator) {if (typeof comparator != 'function') {comparator = function (num, pivot) {return num >= pivot;};}let i = l;for (let j = l; j < r; j++) {if (comparator(arr[j], arr[r])) {[arr[i], arr[j]] = [arr[j], arr[i]];i++;}}// 将 pivot 换到分界点[arr[i], arr[r]] = [arr[r], arr[i]];// 返回 pivot 的下标return i;}/*** 寻找第 k 大元素* 如果 pivot 的下标刚好是 k - 1,那我们就找到了* 如果下标大于 k - 1,那就在 [left, pivotIndex - 1] 这段找第 k 大元素* 如果下标小于 k - 1,那就对 [pivotIndex + 1, right] 这段找第 k - pivotIndex + left- 1 大元素* @param {number[]} list* @param {number} left* @param {number} right* @param {number} k* @param {function} comparator*/function quickSelect(list, k, left = 0, right = list.length - 1, comparator) {if (left >= right) return list[left];const pivotIndex = partition(list, left, right, comparator);if (pivotIndex - left === k - 1) return list[pivotIndex];else if (pivotIndex - left > k - 1)return quickSelect(list, k, left, pivotIndex - 1, comparator);else {return quickSelect(list,k - pivotIndex + left - 1,pivotIndex + 1,right,comparator,);}}
