Open azl397985856 opened 2 years ago
Java Code:
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map =new HashMap<>();
int len = nums.length;
int maxCount=1;
for(int i=0;i<len;i++){
int count = map.getOrDefault(nums[i],0)+1;
if(count>maxCount){
maxCount = count;
}
map.put(nums[i],count);
}
List<List<Integer>> list = new ArrayList<>(maxCount+1);
for(int i=0;i<maxCount+1;i++){
List<Integer> l = new ArrayList<>();
list.add(l);
}
//遍历map,放到list中
for(Integer key:map.keySet()){
Integer count = map.get(key);
List<Integer> mid = list.get(count);
mid.add(key);
}
//从数组的后面开始遍历取k个
int[] res = new int[k];
int index=0;
for(int i=maxCount;i>=0;i--){
if(index>=k){
break;
}
List<Integer> items = list.get(i);
if(!items.isEmpty()){//说明有值
for(Integer item:items){
res[index++]=item;
}
}
}
return res;
}
}
Map和桶数字开销 Space O(N), 桶排序开销还是Time O(N)遍历.
就这个机会把所有的排序看了一遍,总算会了点。
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap();
for(int n : nums){
map.put(n, map.getOrDefault(n, 0) + 1);
}
List[] buckets = new List[nums.length + 1];
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
int val = entry.getValue();
if(buckets[val] == null){
buckets[val] = new ArrayList();
}
buckets[val].add(entry.getKey());
}
int[] res = new int[k];
int id = 0;
for(int i = buckets.length - 1; i > 0; i --){
if(buckets[i] != null){
for(int j = 0; j < buckets[i].size(); j++){
res[id++] = (int) buckets[i].get(j);
if(id == k) return res;
}
}
}
return res;
}
}
# 题解
# 1.创建一个字典,遍历数组将数组中元素出现次数记录到字典中
# 2.将字典转化为列表l,对列表l按照频次进行排序
# 3.把排序列表的前k个数字放到列表res并返回
# 复杂度分析
# 时间复杂度O(nlogn),空间复杂度O(n)
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
dict = {}
for i in range(len(nums)):
if nums[i] not in dict:
dict[nums[i]] = 1
else:
dict[nums[i]] += 1
l = list(dict.items())
sorted_l = sorted(l,key = lambda x:x[1],reverse = True)
res = []
for i in range(k):
res.append(sorted_l[i][0])
return res
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count = {}
# empty array with the size of nums + 1
frequency = [[] for i in range(len(nums) + 1)]
# count each value, if not exist, set to default 0
for n in nums:
count[n] = 1 + count.get(n, 0)
# going through each counted value
for n, c in count.items():
frequency[c].append(n) # the value n appears c times
res = []
# find most frequent value
for i in range(len(frequency) - 1, 0, -1): # start from last element to 0, step is -1
for n in frequency[i]: # go through every value in index i
res.append(n)
if len(res) == k:
return res
因为是统计频率最高的 K 个元素,所以使用 map 统计下每个元素在数组中的出现频率,然后维护一个 k 个大小的小根堆,往小根堆中添加了元素后,如果此时小根堆大小超过 k 了,那么就移除堆顶元素
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
// 根据map的value值排序
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((a, b) -> {
return a.getValue() - b.getValue();
});
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
queue.add(entry);
if (queue.size() > k) {
queue.poll();
}
}
int[] result = new int[k];
for (int i = 0; i < result.length; i++) {
result[i] = queue.poll().getKey();
}
return result;
}
}
时间复杂度: O(nlogK) 空间复杂度: O(n)
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
return [x[0] for x in Counter(nums).most_common(k)
时间复杂度 Python 的 Counter 是字典 dict 的子类,所以插入字典统计频次的复杂度是 O(n)。Counter 的 most_common 内部实现是 heapq 的 nlargest,本质上就是用的最小堆。所以总和时间复杂度是 O(n logn)。空间复杂度 O(n)
var topKFrequent = function(nums, k) {
let result = []
let keyMaps = new Map()
nums.forEach(element => {
keyMaps.set(element, (keyMaps.get(element) || 0) + 1)
});
keyMaps.forEach((val, key) => {
result.push({
key,
val
})
})
result.sort((a, b) => b.val - a.val)
let res = []
for (let index = 0; index < k; index++) {
res.push(result[index].key)
}
return res
};
构建一个字典,其值都为0,然后遍历数组,用字典进行计数,返回字典value最大的前k个key。
def fun(nums,k):
nums_dict=dict.fromkeys(set(nums),0)
for i in nums:
nums_dict[i]+=1
print(nums_dict)
a=list(nums_dict.values())
a.sort()
a.reverse()
res=[]
for key,v in nums_dict.items():
if v in a[:k]:
res.append(key)
return res
nums = [1,1,1,2,2,3]
k = 2
print(fun(nums,k))
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for (int i=0; i<nums.length; ++i) {
map.put(nums[i],map.getOrDefault(nums[i],0)+1);
}
System.out.println(map);
List<Integer>[] bucket = new List[nums.length+1];
// int[] a = new int[10];
for (int key : map.keySet()){
int freq = map.get(key);
if (bucket[freq] == null) {
bucket[freq] = new LinkedList<>();
}
bucket[freq].add(key);
}
int[] res = new int[k];
int m = 0;
for (int j = nums.length; j > 0; --j) {
if (bucket[j] != null) {
for (int val:bucket[j]) {
// System.out.println(val);
if (m == k) {
return res;
}
res[m] =val;
++m;
}
}
// if (res[k] )
}
// res.
return res;
}
}
class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: dict = {}
for i in nums:
if i not in dict:
dict[i] = 1
else:
dict[i] += 1
res = sorted(dict.keys(), key = lambda x: dict[x])
fin = []
while k>0:
fin.append(res.pop())
k-=1
return fin
先用HashMap统计,再排序
class Solution {
public class Compo{
int value;
int count;
Compo(int value, int count) {
this.value = value;
this.count = count;
}
}
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> counts = new HashMap<>();
for(int i:nums) {
counts.merge(i, 1, Integer::sum);
}
List<Compo> compos = new ArrayList<>();
for(Map.Entry<Integer,Integer> entry:counts.entrySet()) {
compos.add(new Compo(entry.getKey(),entry.getValue()));
}
compos.sort(new Comparator<Compo>() {
@Override
public int compare(Compo o1, Compo o2) {
return o2.count - o1.count;
}
});
int[] result = new int[k];
int i = 0;
for(Compo compo:compos) {
if(i < k) {
result[i] = compo.value;
i++;
} else {
break;
}
}
return result;
}
}
时间复杂度O(NLogN) 空间复杂度O(N)
https://leetcode.com/problems/top-k-frequent-elements/
class Solution {
public int[] topKFrequent(int[] nums, int k) {
if(nums == null || nums.length == 0){
return new int[]{};
}
Map<Integer, Integer> map = new HashMap<>();
for(int num: nums){
map.put(num, map.getOrDefault(num, 0) + 1);
}
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> map.get(a) - map.get(b));
for(int key: map.keySet()){
if(pq.size() != k){
pq.offer(key);
}else if(map.get(key) > map.get(pq.peek())){
pq.poll();
pq.offer(key);
}
}
int[] res = new int[k];
for(int i = 0; i < k; i++){
res[i] = pq.poll();
}
return res;
}
}
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
hashmap = defaultdict(int)
for i in range(len(nums)):
hashmap[nums[i]] += 1
heap = []
for num, freq in hashmap.items():
heapq.heappush(heap, (freq, num))
if len(heap) > k:
heapq.heappop(heap)
return [num for freq, num in heap]
Time complexity O(NlogK) Space complexity O(N)
利用 map
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent = function(nums, k) {
let map = new Map(), arr = [...new Set(nums)];
nums.map((num) => {
if(map.has(num)) {
map.set(num, map.get(num) + 1);
} else {
map.set(num, 1);
}
})
return arr.sort((a, b) => map.get(b) - map.get(a)).slice(0, k);
};
复杂度分析
哈希表计数+排序
桶排序
# 哈希表计数+排序
class Solution(object):
def topKFrequent(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
cnt = Counter(nums)
order = sorted(cnt.items(), key=lambda x:x[1], reverse=True)
return [x[0] for x in order[0 : k]]
# 桶排序
class Solution(object):
def topKFrequent(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
cnt = Counter(nums)
bucket = [[] for i in range(len(nums) + 1)]
for key in cnt.keys():
bucket[cnt[key]].append(key)
res = []
for i in range(len(nums), -1, -1):
if not k:
return res
if bucket[i]:
for j in bucket[i]:
res.append(j)
k -= 1
哈希表计数+排序
桶排序
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
fre_dict = {}
ans = []
for num in nums:
if num not in fre_dict:
fre_dict[num] = 1
fre_dict[num] += 1
sorted_dict = sorted(fre_dict.items(), key = lambda x:x[1], reverse = True)
print(sorted_dict)
for i in range(k):
ans.append(sorted_dict[i][0])
return ans
时间复杂度:O(N) 空间复杂度:O(N)
思路:
代码(C++):
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> freq;
for (auto n : nums) // o(n)
freq[n]++;
vector<pair<int, int>> elements(freq.begin(), freq.end());
sort(elements.begin(), elements.end(),
[](const pair<int, int> a, const pair<int, int> b) {
return a.second > b.second;
});
vector<int> res;
for (auto f : elements) { // o(k)
res.push_back(f.first);
if (--k == 0) return res;
}
return {};
}
};
hash table + heap sort
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> times;
for(auto& num : nums)
{
if(times.count(num) == 0)
{
times[num] = 1;
}
else
{
times[num]++;
}
}
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> q;
for(auto it : times)
{
if(q.size() != k)
{
q.push(make_pair(it.second, it.first));
}
else
{
if(it.second > q.top().first)
{
q.pop();
q.push(make_pair(it.second, it.first));
}
}
}
vector<int> res;
while(!q.empty())
{
res.push_back(q.top().second);
q.pop();
}
return res;
}
};
map记录element出现的频率, 数组排序
let topKFrequent = function(nums, k) {
let map = new Map(), arr = [...new Set(nums)]
nums.map(num => {
map.set(num, map.has(num) ? map.get(num) + 1 : 1)
})
return arr.sort((a, b) => map.get(b) - map.get(a)).slice(0, k);
};
class Solution {
public int[] topKFrequent(int[] nums, int k) {
List<Integer> res = new LinkedList<>();
List<Integer>[] bucket = new List[nums.length + 1];
Map<Integer, Integer> counter = new HashMap<>();
for (int num: nums)
counter.put(num, counter.getOrDefault(num, 0) + 1);
for (Map.Entry<Integer, Integer> entry: counter.entrySet()) {
int val = entry.getValue();
if (bucket[val] == null)
bucket[val] = new LinkedList<>();
bucket[val].add(entry.getKey());
}
int kNum = 0;
for (int i = bucket.length - 1; i >= 0; i--)
if (bucket[i] != null)
for (int elem: bucket[i]){
res.add(elem);
kNum++;
}
int[] ret = new int[k];
for (int i = 0; i < ret.length; i++)
ret[i] = res.get(i);
return ret;
}
}
哈希表保存出现次数,最小堆保存次数。遍历所有的出现次数,堆的大小超过k后,判断下一个是否大于堆顶的次数,如大于则取代其成为新的堆顶。遍历完毕后在堆中的元素即为数组前k个高频元素。
public class Day20 {
public int[] topKFrequent(int[] nums,int k) {
HashMap<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if(map.containsKey(nums[i])){
int count = map.get(nums[i]);
count++;
map.put(nums[i],count);
}else{
map.put(nums[i],1);
}
}
// System.out.println("map:"+map);
//res[k][0]==次数 res[k][1]==值
PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0]-o2[0];
}
});//堆顶为最小值
Iterator<Integer> keys = map.keySet().iterator();
while (keys.hasNext()){
int val = keys.next();//数组元素
int count = map.get(val);//出现次数
if(queue.size()<k){
//System.out.println("小于=k:"+count+","+val);
queue.offer(new int[]{count,val});
}else {
//System.out.println("大于k:"+count+","+val+",min:"+queue.peek()[0]);
if(queue.peek()[0]<count){
queue.poll();
queue.offer(new int[]{count,val});
}
}
}
int [] res= new int[k];
for (int i = 0; i < k; i++) {
res[i] = queue.poll()[1];
}
return res;
}
}
时间复杂度:O(nlogn)
空间复杂度:O(n)
先用map计数,再用priority_queue pop出k个即可
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;
}
};
var topKFrequent = function(nums, k) { let obj = {}; let arr = []; nums.forEach((value, index) => { if (obj[value]) { obj[value]++; } else { obj[value] = 1; } }); arr = Object.entries(obj); arr.sort(function (x, y) { return y[1] - x[1]; });
let arr2 = [];
for (let i = 0; i < k; i++) {
arr2[i] = arr[i][0];
}
return arr2;
};
数据整合后放入map,key为数据,value为出现次数 利用小顶堆排序,保持堆中数据数量不超过K, 堆容量小于k直接放入 大于k的时候和堆顶元素比较大小,如果大于将当前数据加入堆中 最后取出堆中数据
public int[] topKFrequent(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
//数据整合后放入map,key为数据,value为出现次数
for (int i = 0; i < nums.length; i++) {
if(map.containsKey(nums[i])){
map.put(nums[i],map.get(nums[i]) + 1);
}else {
map.put(nums[i],1);
}
}
//利用小顶堆排序
PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return map.get(a) - map.get(b);
}
});
for (Integer key : map.keySet()) {
//维护一个k大小的堆,小于k直接放入
if (pq.size() < k) {
pq.add(key);
//大于k的时候和堆顶元素比较大小 如果大于将堆首删除,加入数据
//堆首永远是最小的
} else if (map.get(key) > map.get(pq.peek())) {
pq.remove();
pq.add(key);
}
}
//取出数据
int[] result = new int[pq.size()];
int length = pq.size();
for (int i = 0; i < length; i++) {
result[i] = pq.remove();
}
return result;
}
**复杂度分析**
- 时间复杂度:O(Nlogk),其中 N 为数组长度,k为堆的大小。
- 空间复杂度:O(N)
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count = collections.Counter(nums)
dp = []
for key,val in count.items():
heappush(dp,(-val,key))
return [heappop(dp)[1] for _ in range(k)]
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
int[] maxK = new int[k];
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i])) {
Integer count = map.get(nums[i]);
map.put(nums[i], ++count);
} else {
map.put(nums[i], 0);
}
}
Queue<Map.Entry<Integer, Integer>> q = new PriorityQueue<>((e1, e2) -> e2.getValue().compareTo(e1.getValue()));
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
q.offer(entry);
}
for (int i = 0; i < k; i++) {
maxK[i] = q.poll().getKey();
}
return maxK;
}
哈希表key存储元素,val存储出现频数,小顶堆排序
class Solution {
public int[] topKFrequent(int[] nums, int k) {
int[] res = new int[k];
HashMap<Integer,Integer> m = new HashMap<>();
for (int num:nums){
m.put(num,m.getOrDefault(num,0)+1);
}
Set<Map.Entry<Integer,Integer>> entries = m.entrySet();
PriorityQueue<Map.Entry<Integer,Integer>> q = new PriorityQueue<>((o1,o2)->o1.getValue()-o2.getValue());
for (Map.Entry<Integer,Integer> entry:entries){
q.offer(entry);
if(q.size()>k){
q.poll();
}
}
for (int i=k-1;i>=0;i--){
res[i] = q.poll().getKey();
}
return res;
}
}
时间复杂度O(nlogk)
空间复杂度O(n)
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
vector<int> ans;
unordered_map<int, int> helper;
priority_queue<pair<int,int>> q;
for(auto i:nums){
helper[i]++;
}
for(auto j:helper){
q.push(pair<int,int>(-j.second,j.first));
if(q.size()>k){
q.pop();
}
}
while(k--){
ans.push_back(q.top().second);
q.pop();
}
return ans;
}
};
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
if not nums:
return []
cnt = collections.Counter(nums)
nums = list(cnt.items())
def partition(nums, left, right):
pivot=nums[left][1]
pivotFull=nums[left]
i,j = left,right
while i<j:
while(i<j and nums[j][1]>=pivot):
j-=1
nums[i]=nums[j]
while(i<j and nums[i][1]<=pivot):
i+=1
nums[j]=nums[i]
nums[i]=pivotFull
return i
def quickSearch(nums, left, right, k):
idx = partition(nums, left, right)
if idx == k:
return [nums[i][0] for i in range(idx,len(nums))]
elif idx < k:
return quickSearch(nums, idx + 1, right, k)
else:
return quickSearch(nums, left, idx - 1, k)
k=len(nums)-k
return quickSearch(nums, 0, len(nums) - 1, k)
利用 hashtable 来进行计数,之后按照频率进行排序即可。
一般的排序算法需要用到 nlogn 的复杂度。题目里让最好保持在 nlogn 之下。 看了题解发现,可以使用 bucket sort 来空间换时间。因为题目里不要求顺序, 所以 bucket 内的排序是不需要的,让复杂度下降到了 O(n).
CPP
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> count_map; // num, frequent
vector<vector<int>> bucket(nums.size()+1);
for (auto &n : nums) {
count_map[n]++;
}
for (auto &[k, v] : count_map) {
bucket[v].push_back(k);
}
vector<int> ret;
for (int i = bucket.size() - 1; i >=0; i--) {
if (bucket[i].size()) {
for (auto &n : bucket[i]) {
if (k) {
ret.push_back(n);
k--;
}
}
}
}
return ret;
}
};
复杂度分析
def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ hashmap={} for i in nums: if i in hashmap: hashmap[i]=hashmap[i]+1 else: hashmap[i]=1 a1 = sorted(hashmap.items(),key = lambda x:x[1],reverse = True)#按照val值从大到小对哈希表排序 result=[] for key in a1: if k<=0: break result.append(key[0]) k=k-1 return result
class Solution {
public int[] topKFrequent(int[] nums, int k) {
// 使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
//桶排序
//将频率作为数组下标,对于出现频率不同的数字集合,存入对应的数组下标
List<Integer>[] list = new List[nums.length+1];
Set<Map.Entry<Integer,Integer>> ms = map.entrySet();
for (Map.Entry entry :ms) {
int key = (int)entry.getKey();
int i = map.get(key);
if(list[i] == null){
list[i] = new ArrayList();
}
list[i].add(key);
}
List<Integer> res = new ArrayList();
// 倒序遍历数组获取出现顺序从大到小的排列
for(int i = list.length - 1;i >= 0 && res.size() < k;i--){
if(list[i] == null) continue;
res.addAll(list[i]);
}
int[] out = new int[res.size()];
for(int a = 0; a < res.size(); a++){
out[a] = res.get(a);
}
return out;
}
}
时间复杂度 O(n) 空间复杂度 O(n)
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
先遍历一遍,用一个哈希表把次数都存起来
然后拿出哈希表中全部的键值对,放进一个优先队列中,优先队列按照value值的大小去排列
最后看k是多少,出队几个就可以了
class Solution {
public int[] topKFrequent(int[] nums, int k) {
int[] res = new int[k];
//先遍历一遍,用一个哈希表把次数都存起来
//然后拿出哈希表中全部的键值对,放进一个优先队列中,优先队列按照value值的大小去排列
//最后看k是多少,出队几个就可以了
Map<Integer,Integer> map = new HashMap<>();
for(int num : nums){
map.put(num, map.getOrDefault(num, 0) + 1);
}
//创建优先队列
PriorityQueue<Map.Entry<Integer,Integer>> prQueue = new PriorityQueue<>(
new Comparator<Map.Entry<Integer,Integer>>(){
@Override
//大的在前面
public int compare(Map.Entry<Integer,Integer> o1, Map.Entry<Integer,Integer> o2){
return o2.getValue().compareTo(o1.getValue());
}
});
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
prQueue.add(entry);
}
for(int i = 0; i < k; i++){
int num = prQueue.poll().getKey();
res[i] = num;
}
return res;
}
}
时间复杂度:$O(n)$
空间复杂度:
哈希表+堆排序
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();
for (int num : nums) {
occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
}
// int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
public int compare(int[] m, int[] n) {
return m[1] - n[1];
}
});
for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
int num = entry.getKey(), count = entry.getValue();
if (queue.size() == k) {
if (queue.peek()[1] < count) {
queue.poll();
queue.offer(new int[]{num, count});
}
} else {
queue.offer(new int[]{num, count});
}
}
int[] ret = new int[k];
for (int i = 0; i < k; ++i) {
ret[i] = queue.poll()[0];
}
return ret;
}
}
var topKFrequent = function(nums, k) {
const numMap = new Map()
for(num of nums) {
numMap.set(num, (numMap.get(num) || 0) + 1)
}
if (numMap.size < k) {
return [...numMap.keys()]
}
return Array.from(numMap.keys())
.sort((left, right) => numMap.get(right) - numMap.get(left))
.slice(0, k)
};
利用map记录出现过的数字和次数,然后返回次数最大的前k个
var topKFrequent = function(nums, k) {
let hash = new Map();
for(let i = 0; i < nums.length; i++) {
if(hash.has(nums[i])){
let num = hash.get(nums[i]);
hash.set(nums[i], num + 1);
} else {
hash.set(nums[i], 1);
}
}
return [...hash].sort((a,b)=>a[1]-b[1]).slice(-k).map(vv=>vv[0])
};
时间复杂度:O(nlogn)
空间复杂度:O(n)
堆
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();
for (int num : nums) {
occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
}
PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
public int compare(int[] m, int[] n) {
return m[1] - n[1];
}
});
for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
int num = entry.getKey(), count = entry.getValue();
if (queue.size() == k) {
if (queue.peek()[1] < count) {
queue.poll();
queue.offer(new int[]{num, count});
}
} else {
queue.offer(new int[]{num, count});
}
}
int[] ret = new int[k];
for (int i = 0; i < k; ++i) {
ret[i] = queue.poll()[0];
}
return ret;
}
}
思路 桶的 key 是值,value 是值等于 key 的列表。 初始化一个桶 bucket,一个哈希表 counter 记录数值频次 从最后一个桶开始遍历直到取出 K 个数
class Solution {
public int[] topKFrequent(int[] nums, int k) {
List<Integer> res = new LinkedList<>();
List<Integer>[] bucket = new List[nums.length + 1];
Map<Integer, Integer> counter = new HashMap<>();
for (int num: nums)
counter.put(num, counter.getOrDefault(num, 0) + 1);
for (Map.Entry<Integer, Integer> entry: counter.entrySet()) {
int val = entry.getValue();
if (bucket[val] == null)
bucket[val] = new LinkedList<>();
bucket[val].add(entry.getKey());
}
int kNum = 0;
for (int i = bucket.length - 1; i >= 0; i--)
if (bucket[i] != null)
for (int elem: bucket[i]){
res.add(elem);
kNum++;
}
int[] ret = new int[k];
for (int i = 0; i < ret.length; i++)
ret[i] = res.get(i);
return ret;
}
}
时间复杂度: O(N) 空间复杂度: O(N)
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
} else if (p == null || q == null) {
return false;
} else if (p.val != q.val) {
return false;
} else {
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
}
}
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count = collections.Counter(nums)
return [item[0] for item in count.most_common(k)]
https://leetcode-cn.com/problems/top-k-frequent-elements/
小顶堆,遍历出现次数数组
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
vector<int> ret;
unordered_map<int, int> mp;
priority_queue<pair<int, int>> pq;
for (auto i : nums) mp[i]++;
for (auto p : mp) {
pq.push(pair<int, int>(-p.second, p.first));
if (pq.size() > k) pq.pop();
}
while (k--) {
ret.push_back(pq.top().second);
pq.pop();
}
reverse(ret.begin(),ret.end());
return ret;
}
};
复杂度分析
循环获取所有值出现的次数,然后转换key 和value的顺序取最大的K个拿出来
public int[] topKFrequent(int[] nums, int k) {
HashMap<Integer, Integer> integerIntegerHashMap = new HashMap<>();
LinkedList<Integer> integers = new LinkedList<>();
List<Integer>[] buckets=new List[nums.length+1];
for (int num:nums) {
integerIntegerHashMap.put(num,integerIntegerHashMap.getOrDefault(num,0)+1);
}
for (Map.Entry<Integer,Integer> entry:integerIntegerHashMap.entrySet()) {
if(buckets[entry.getValue()]==null){
buckets[entry.getValue()]=new LinkedList<Integer>();
}
buckets[entry.getValue()].add(entry.getKey());
}
for(int i=buckets.length-1;i>=0;i++){
if(buckets[i]!=null){
for(int element:buckets[i]){
integers.add(element);
}
}
}
int []res= new int[k];
for(int i=0;i<res.length;i++){
res[i]=integers.get(i);
}
return res;
Code:
public class Solution { public int[] TopKFrequent(int[] nums, int k) { Dictionary<int, int> dicNums = new Dictionary<int, int>(); for (int i = 0; i < nums.Length; i++) { if (dicNums.ContainsKey(nums[i])) { dicNums[nums[i]]++; } else { dicNums.Add(nums[i], 1); } }
List<int>[] bucket = new List<int>[nums.Length + 1];
foreach (var item in dicNums)
{
if (bucket[item.Value] == null)
{
bucket[item.Value] = new List<int>();
}
bucket[item.Value].Add(item.Key);
}
int count = 0;
int[] result = new int[k];
for (int i = bucket.Length - 1; i >= 0 ; i--)
{
if (bucket[i] == null || bucket[i].Count == 0)
continue;
foreach(int item in bucket[i])
{
result[count++] = item;
if(count == k)
return result;
}
}
return result;
}
}
堆
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
// pair<count, val>
// top k, min heap(小根堆)
using E = std::pair<int, int>;
std::priority_queue<E, std::vector<E>, std::greater<E>> minHeap;
map<int, int> counter;
for (auto e : nums) {
++counter[e];
}
for (auto& x : counter) {
auto pair = make_pair(x.second, x.first);
if (minHeap.size() == k) {
if (pair < minHeap.top()) continue;
minHeap.pop();
}
minHeap.push(std::move(pair));
}
std::vector<int> res(minHeap.size());
k = res.size();
while(!minHeap.empty()) {
res[--k] = minHeap.top().second;
minHeap.pop();
}
return res;
}
};
复杂度分析
class Solution { public int[] topKFrequent(int[] nums, int k) { Map<Integer, Integer> map = new HashMap<>(); for (int num : nums) { map.put(num, map.getOrDefault(num, 0) + 1); }
PriorityQueue<int[]> pq = new PriorityQueue<>(
(int[] a, int[] b) -> a[1] - b[1]
);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
int num = entry.getKey(), count = entry.getValue();
if (pq.size() == k) {
if (pq.peek()[1] < count) {
pq.poll();
pq.offer(new int[]{num, count});
}
} else {
pq.offer(new int[]{num, count});
}
}
int[] ans = new int[k];
for (int i = 0; i < k; i++) {
ans[i] = pq.poll()[0];
}
return ans;
}
}
++
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
进阶:你所设计算法的时间复杂度 必须 优于 O(n log n)
,其中 n
是数组大小。
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
counts = {}
max_count = 0
for n in nums:
counts[n] = counts.get(n, 0) + 1
max_count = max(max_count, counts[n])
buckets = [[] for _ in range(max_count)] # List[List[]] 内部有max_count个[]
for n, num in counts.items():
buckets[num - 1].append(n) # 可能有多个数字是一样的频率
res = []
for i in range(len(buckets)-1, -1, -1):
res.extend(buckets[i])
if len(res) >= k:
break
return res[:k]
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> counts;
int max_count = 0;
for(int num: nums){
max_count = max(max_count, ++counts[num]);
}
vector<vector<int>> buckets(max_count);
for(pair<int, int> p: counts){
buckets[p.second - 1].emplace_back(p.first);
}
vector<int> res;
for(int i = max_count - 1; i >= 0; i--){
for(int n: buckets[i]){
res.emplace_back(n);
if(res.size() == k){
return res;
}
}
}
return res;
}
};
需要考虑数组中的重复的数组
class Solution { public int[] topKFrequent(int[] num, int k) { HashMap<Integer,Integer> map = new HashMap<>(); ArrayList<Integer> list = new ArrayList<>(); for(int i: num){ map.put(i,map.getOrDefault(i,0)+1); if(!list.contains(i))list.add(i); } int arr[] = new int[list.size()]; int j=0; for(int i:list)arr[j++]=i; fun(map,arr,0,arr.length-1); //对list进行排序,注意排序的规则是根据 map所对应的value的值。 //又因为时间复杂度限制为nlogn 只能选择快排或者归并 int arr_s[]=new int[k]; for(int i=0;i<k;i++){ arr_s[i] = arr[i]; } return arr_s; } //按照从降序排序 public void fun(HashMap<Integer,Integer> map,int[]arr,int start,int end){ if(start>end)return; int temp_value=map.get(arr[start]); int temp=arr[start]; int l=start,r=end; while (l<r){ while (l<r&&map.get(arr[r])<=temp_value)r--; arr[l]=arr[r]; while (l<r&&map.get(arr[l])>=temp_value)l++; arr[r] = arr[l]; } arr[l]=temp; fun(map,arr,start,l-1); fun(map,arr,l+1,end); } }
C++ Code:
class Solution {
public:
class mycomparison {
public:
bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
return lhs.second > rhs.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> map;
for (int i = 0; i < nums.size(); i++) {
map[nums[i]]++;
}
priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;
for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
pri_que.push(*it);
if (pri_que.size() > k) {
pri_que.pop();
}
}
vector<int> ans(k);
for (int i = k - 1; i >= 0; i--) {
ans[i] = pri_que.top().first;
pri_que.pop();
}
return ans;
}
};
复杂度分析
令 n 为数组长度。
C++ Code:
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> m;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
vector<int> res;
for (auto a : nums) {
++m[a];
}
for (auto& [key, val] : m) {
q.push(pair<int, int>(val, key));
if (q.size() > k) {
q.pop();
}
}
while (!q.empty()) {
res.emplace_back(q.top().second);
q.pop();
}
return res;
}
};
复杂度分析
//12-31 Happy new year!
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int,int> mp;
int len = nums.size();
vector<int> ans(k,0);
for (int i = 0; i < len; i++) {
mp[nums[i]]++;
}
vector<pair<int, int>> tmp;
for (auto &p : mp) {
tmp.push_back({p.second, p.first});
}
sort(tmp.rbegin(),tmp.rend());
for (int i = 0; i < k; i++) {
ans[i] = tmp[i].second;
}
return ans;
}
};
347. 前 K 个高频元素
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/top-k-frequent-elements/
前置知识
题目描述
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
示例 2:
输入: nums = [1], k = 1 输出: [1]
提示:
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/top-k-frequent-elements 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。