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 题目汇总