加载中...
剑指 Offer II 060-出现频率最高的 k 个数字
发表于:2021-12-03 | 分类: 中等
字数统计: 1.4k | 阅读时长: 8分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/g5c51o

中文题目

给定一个整数数组 nums 和一个整数 k ,请返回其中出现频率前 k 高的元素。可以按 任意顺序 返回答案。

 

示例 1:

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

示例 2:

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

 

提示:

  • 1 <= nums.length <= 105
  • k 的取值范围是 [1, 数组中不相同的元素的个数]
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

 

进阶:所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。

 

注意:本题与主站 347 题相同:https://leetcode-cn.com/problems/top-k-frequent-elements/

通过代码

高赞题解

思路和心得:

(一)最小堆

1.维持一个容量为k的最小堆

[]
class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: num_freq = collections.Counter(nums) minHeap = [] for x, f in num_freq.items(): if len(minHeap) == k: if minHeap[0][0] < f: heapq.heappop(minHeap) heapq.heappush(minHeap, (f, x)) else: heapq.heappush(minHeap, (f, x)) res = [] while minHeap: f, x = heapq.heappop(minHeap) res.append(x) return res
[]
class Solution { public: struct cmp1 { bool operator () (pair<int,int> & a, pair<int, int> & b) { return a.second > b.second; } }; vector<int> topKFrequent(vector<int>& nums, int k) { unordered_map<int, int> num_freq; for (int x : nums) num_freq[x] ++; priority_queue<pair<int,int>, vector<pair<int,int>>, cmp1> minHeap; for (auto [x, f] : num_freq) { if (minHeap.size() == k) { if (minHeap.top().second < f) { minHeap.pop(); minHeap.push({x, f}); } } else { minHeap.push({x, f}); } } vector<int> res; while (!minHeap.empty()) { auto [x, f] = minHeap.top(); minHeap.pop(); res.push_back(x); } return res; } };
[]
class xf { public int x; public int f; xf(int x_, int f_) { x = x_; f = f_; } } class Solution { public int[] topKFrequent(int[] nums, int k) { Map<Integer, Integer> num_freq = new HashMap<>(); for (int x : nums) num_freq.put(x, num_freq.getOrDefault(x, 0) + 1); PriorityQueue<xf> minHeap = new PriorityQueue<>(new Comparator<xf>() { public int compare(xf a, xf b) { return a.f - b.f; } }); for (Map.Entry<Integer, Integer> entry : num_freq.entrySet()) { int x = entry.getKey(); int f = entry.getValue(); if (minHeap.size() == k) { if (minHeap.peek().f < f) { minHeap.poll(); minHeap.offer(new xf(x, f)); } } else { minHeap.offer(new xf(x, f)); } } int [] res = new int [k]; for (int i = 0; i < k; i ++) { xf a = minHeap.poll(); res[i] = a.x; } return res; } }

c++ 自定义类,运算符重载,千万不要忘记 const!!!!!!!!

[]
struct xf { int x; int f; xf(int x_, int f_) { x = x_; f = f_; } //重载 < 运算符 bool operator <(const xf b) const { return f > b.f; } }; class Solution { public: vector<int> topKFrequent(vector<int>& nums, int k) { unordered_map<int, int> num_freq; for (int x : nums) num_freq[x] ++; priority_queue<xf> minHeap; for (auto [x, f] : num_freq) { if ((int)minHeap.size() == k) { if (minHeap.top().f < f) { minHeap.pop(); minHeap.push( xf(x, f)); } } else { minHeap.push( xf(x, f)); } } vector<int> res; while (!minHeap.empty()) { xf a = minHeap.top(); minHeap.pop(); res.push_back(a.x); } return res; } };

(二)快排–分治

[]
class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: n = len(nums) num_freq = collections.Counter(nums) self.res = [] xfs = list(num_freq.items()) xfn = len(xfs) self.quick_sort(xfs, 0, xfn - 1, k) return self.res #-------大于等于的都交换到左侧。快排的第三种写法 def quick_sort(self, xfs, l: int, r: int, k: int) -> None: pivot_xf = xfs[l] pivot_f = xfs[l][1] idx = l for i in range(l + 1, r + 1, 1): if xfs[i][1] >= pivot_f: idx += 1 xfs[idx], xfs[i] = xfs[i], xfs[idx] xfs[l], xfs[idx] = xfs[idx], xfs[l] if k == idx - l + 1: for i in range(l, idx + 1): self.res.append(xfs[i][0]) elif k < idx - l + 1: self.quick_sort(xfs, l, idx - 1, k) else: for i in range(l, idx + 1): self.res.append(xfs[i][0]) self.quick_sort(xfs, idx + 1, r, k - (idx - l + 1))
[]
class Solution { public: vector<pair<int, int>> xfs; vector<int> res; vector<int> topKFrequent(vector<int>& nums, int k) { unordered_map<int, int> num_freq; for (int x : nums) num_freq[x] ++; for (auto xf: num_freq) xfs.push_back(xf); int xfn = xfs.size(); quick_sort(0, xfn -1, k); return res; } void quick_sort(int l, int r, int k) { pair<int, int> pivot_xf = xfs[l]; int pivot_f = pivot_xf.second; int idx = l; for (int i = l + 1; i < r + 1; i ++) { if (pivot_f <= xfs[i].second) { idx ++; swap(xfs[idx], xfs[i]); } } swap(xfs[l], xfs[idx]); if (k == idx - l + 1) { for (int i = l; i < idx + 1; i ++) { res.push_back(xfs[i].first); } } else if (k < idx - l + 1) { quick_sort(l, idx - 1, k); } else { for (int i = l; i < idx + 1; i ++) res.push_back(xfs[i].first); quick_sort(idx + 1, r, k - (idx - l + 1)); } } };
[]
class Node { int x; int f; Node(int x_, int f_) { x = x_; f = f_; } } class Solution { List<Node> xfs = new ArrayList<>(); int [] res; int res_i = 0; public int[] topKFrequent(int[] nums, int k) { res = new int [k]; Map<Integer, Integer> num_freq = new HashMap<>(); for (int x : nums) num_freq.put(x, num_freq.getOrDefault(x, 0) + 1); for (Map.Entry<Integer, Integer> entry : num_freq.entrySet()) { int x = entry.getKey(); int f = entry.getValue(); xfs.add(new Node(x, f)); } int xfn = xfs.size(); quick_sort(0, xfn - 1, k); return res; } public void quick_sort(int l, int r, int k) { Node pivot_xf = xfs.get(l); int pivot_f = pivot_xf.f; int idx = l; for (int i = l + 1; i < r + 1; i ++) { if (pivot_f <= xfs.get(i).f) { idx ++; Node tmp = xfs.get(idx); xfs.set(idx, xfs.get(i)); xfs.set(i, tmp); } } Node tmp = xfs.get(idx); xfs.set(idx, xfs.get(l)); xfs.set(l, tmp); if (k == idx - l + 1) { for (int i = l; i < idx + 1; i ++) res[res_i ++] = xfs.get(i).x; } else if (k < idx - l + 1) { quick_sort(l, idx - 1, k); } else { for (int i = l; i < idx + 1; i ++) res[res_i ++] = xfs.get(i).x; quick_sort(idx + 1, r, k - (idx - l + 1)); } } }

统计信息

通过次数 提交次数 AC比率
3656 5393 67.8%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
剑指 Offer II 059-数据流的第 K 大数值
下一篇:
剑指 Offer II 061-和最小的 k 个数对
本文目录
本文目录