[LeetCode] 347. Top K Frequent Elements 前K个高频元素
Given a non-empty array of integers, return the k most frequent elements.
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
Example 2:
Input: nums = [1], k = 1
Output: [1]
Note:
- You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
- Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
给一个非空整数数组,返回前k个频率最高的元素。k总是合理的,1 ≤k1 ≤独立元素的数量。要求算法时间复杂度必须优于O(n log n),n是数组长度。
解法1: 桶排序Bucket Sort, Time: O(n), Space: O(n)
1. 遍历数组nums,利用Hash map统计每个数字出现的次数。
2. 遍历map,初始化一个行数为len(nums) + 1的二维数组,将出现次数为i ( i∈[1, n] )的所有数字加到第i行。
3. 逆序遍历二维数组(从频率高的开始),将其中的前k行的元素输出。
解法2:快排Quick select, Time: O(n) ~ O(n^2), O(n) on average. Space: O(n)
解法3: 最大堆max heap,Time: O(n * log k),其中k为独立元素的个数, Space: O(n)。
1. 先用Hash map统计所有数字出现的次数。
2. 建立一个大小为k的最大堆max heap,遍历map,将出现次数和数字组成的pair推到heap中,堆顶为出现次数最多的pair,遍历结束后,把heap中的元素从堆顶一个个的取出即可。
解法4:利用Java中的TreeMap, Tree map是一个有序的key-value集合,它是通过红黑树实现的。利用map可统计,又是按key排序的。
Java: Bucket Sort
public List<Integer> topKFrequent(int[] nums, int k) { List<Integer>[] bucket = new List[nums.length + 1]; Map<Integer, Integer> frequencyMap = new HashMap<Integer, Integer>(); for (int n : nums) { frequencyMap.put(n, frequencyMap.getOrDefault(n, 0) + 1); } for (int key : frequencyMap.keySet()) { int frequency = frequencyMap.get(key); if (bucket[frequency] == null) { bucket[frequency] = new ArrayList<>(); } bucket[frequency].add(key); } List<Integer> res = new ArrayList<>(); for (int pos = bucket.length - 1; pos >= 0 && res.size() < k; pos--) { if (bucket[pos] != null) { res.addAll(bucket[pos]); } } return res; }
Java: Solution 1
public List<Integer> topKFrequent(int[] nums, int k) { //count the frequency for each element HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); for(int num: nums){ if(map.containsKey(num)){ map.put(num, map.get(num)+1); }else{ map.put(num, 1); } } //get the max frequency int max = 0; for(Map.Entry<Integer, Integer> entry: map.entrySet()){ max = Math.max(max, entry.getValue()); } //initialize an array of ArrayList. index is frequency, value is list of numbers ArrayList<Integer>[] arr = (ArrayList<Integer>[]) new ArrayList[max+1]; for(int i=1; i<=max; i++){ arr[i]=new ArrayList<Integer>(); } for(Map.Entry<Integer, Integer> entry: map.entrySet()){ int count = entry.getValue(); int number = entry.getKey(); arr[count].add(number); } List<Integer> result = new ArrayList<Integer>(); //add most frequent numbers to result for(int j=max; j>=1; j--){ if(arr[j].size()>0){ for(int a: arr[j]){ result.add(a); //if size==k, stop if(result.size()==k){ break; } } } } return result; }
Java: Heap
class Pair{ int num; int count; public Pair(int num, int count){ this.num=num; this.count=count; } } public class Solution { public List<Integer> topKFrequent(int[] nums, int k) { //count the frequency for each element HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); for(int num: nums){ if(map.containsKey(num)){ map.put(num, map.get(num)+1); }else{ map.put(num, 1); } } // create a min heap PriorityQueue<Pair> queue = new PriorityQueue<Pair>(new Comparator<Pair>(){ public int compare(Pair a, Pair b){ return a.count-b.count; } }); //maintain a heap of size k. for(Map.Entry<Integer, Integer> entry: map.entrySet()){ Pair p = new Pair(entry.getKey(), entry.getValue()); queue.offer(p); if(queue.size()>k){ queue.poll(); } } //get all elements from the heap List<Integer> result = new ArrayList<Integer>(); while(queue.size()>0){ result.add(queue.poll().num); } //reverse the order Collections.reverse(result); return result; } }
Java:
// use treeMap. Use freqncy as the key so we can get all freqencies in order public class Solution { public List<Integer> topKFrequent(int[] nums, int k) { Map<Integer, Integer> map = new HashMap<>(); for(int n: nums){ map.put(n, map.getOrDefault(n,0)+1); } TreeMap<Integer, List<Integer>> freqMap = new TreeMap<>(); for(int num : map.keySet()){ int freq = map.get(num); if(!freqMap.containsKey(freq)){ freqMap.put(freq, new LinkedList<>()); } freqMap.get(freq).add(num); } List<Integer> res = new ArrayList<>(); while(res.size()<k){ Map.Entry<Integer, List<Integer>> entry = freqMap.pollLastEntry(); res.addAll(entry.getValue()); } return res; } }
Python: Solution 1
class Solution(object): def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ n = len(nums) cntDict = collections.defaultdict(int) for i in nums: cntDict[i] += 1 freqList = [[] for i in range(n + 1)] for p in cntDict: freqList[cntDict[p]] += p, ans = [] for p in range(n, 0, -1): ans += freqList[p] return ans[:k]
Python: Solution 1
class Solution(object): def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ counts = collections.Counter(nums) buckets = [[] for _ in xrange(len(nums)+1)] for i, count in counts.iteritems(): buckets[count].append(i) result = [] for i in reversed(xrange(len(buckets))): for j in xrange(len(buckets[i])): result.append(buckets[i][j]) if len(result) == k: return result return result
Python: Quick Select Solution
# Time: O(n) ~ O(n^2), O(n) on average. # Space: O(n) from random import randint class Solution(object): def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ counts = collections.Counter(nums) p = [] for key, val in counts.iteritems(): p.append((-val, key)) self.kthElement(p, k) result = [] for i in xrange(k): result.append(p[i][1]) return result def kthElement(self, nums, k): def PartitionAroundPivot(left, right, pivot_idx, nums): pivot_value = nums[pivot_idx] new_pivot_idx = left nums[pivot_idx], nums[right] = nums[right], nums[pivot_idx] for i in xrange(left, right): if nums[i] < pivot_value: nums[i], nums[new_pivot_idx] = nums[new_pivot_idx], nums[i] new_pivot_idx += 1 nums[right], nums[new_pivot_idx] = nums[new_pivot_idx], nums[right] return new_pivot_idx left, right = 0, len(nums) - 1 while left <= right: pivot_idx = randint(left, right) new_pivot_idx = PartitionAroundPivot(left, right, pivot_idx, nums) if new_pivot_idx == k - 1: return elif new_pivot_idx > k - 1: right = new_pivot_idx - 1 else: # new_pivot_idx < k - 1. left = new_pivot_idx + 1
Python: Heap
import collections import heapq class Solution(object): def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ counts = collections.Counter(nums) heap = [] for key, cnt in counts.items(): if len(heap) < k: heapq.heappush(heap, (cnt, key)) else: if heap[0][0] < cnt: heapq.heappop(heap) heapq.heappush(heap, (cnt, key)) return [x[1] for x in heap]
Python: Solution 2, most_common实现了heapq(堆)模块
class Solution(object): def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ c = collections.Counter(nums) return [x[0] for x in c.most_common(k)]
Python: Solution 2
class Solution3(object): def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ return [key for key, _ in collections.Counter(nums).most_common(k)]
C++: Solutoin 1
class Solution { public: vector<int> topKFrequent(vector<int>& nums, int k) { unordered_map<int, int> m; vector<vector<int>> bucket(nums.size() + 1); vector<int> res; for (auto a : nums) ++m[a]; for (auto it : m) { bucket[it.second].push_back(it.first); } for (int i = nums.size(); i >= 0; --i) { for (int j = 0; j < bucket[i].size(); ++j) { res.push_back(bucket[i][j]); if (res.size() == k) return res; } } return res; } };
C++: Solution 2
class Solution { public: vector<int> topKFrequent(vector<int>& nums, int k) { unordered_map<int, int> m; priority_queue<pair<int, int>> q; vector<int> res; for (auto a : nums) ++m[a]; for (auto it : m) q.push({it.second, it.first}); for (int i = 0; i < k; ++i) { res.push_back(q.top().second); q.pop(); } return res; } };
类似题目:
[LeetCode] 215. Kth Largest Element in an Array 数组中第k大的元素
[LeetCode] 192. Word Frequency 词频
[LeetCode] 692. Top K Frequent Words 前K个高频单词
All LeetCode Questions List 题目汇总