leetcode-pp / 91alg-6-daily-check

91 算法第六期打卡仓库
28 stars 0 forks source link

【Day 20 】2021-12-31 - 347. 前 K 个高频元素 #27

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

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 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

wxj783428795 commented 2 years ago

思路

  1. 遍历数组,用一个map记录数字和数字出现的次数。
  2. 取出map的键值对,按次数从高到低排序
  3. 取排序后数组的前k个值的key

代码

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function (nums, k) {
    let map = {};
    for (let num of nums) {
        if (map[num] === undefined) {
            map[num] = 1;
        } else {
            map[num] += 1;
        }
    }
    return Object.entries(map).sort((a, b) => b[1] - a[1]).slice(0,k).map(i => i[0])
};

复杂度分析

复杂度分析不是很会,不一定对,如果有错,请指正。

思路2

  1. 遍历数组,用一个map记录数字和数字出现的次数。
  2. 桶排序

代码2

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function (nums, k) {
    let map = {};
    for (let num of nums) {
        if (map[num] === undefined) {
            map[num] = 1;
        } else {
            map[num] += 1;
        }
    }
    let arr = [];
    Object.entries(map).map((item) => {
        if (arr[item[1]] === undefined) {
            arr[item[1]] = [item[0]];
        } else {
            arr[item[1]].push(item[0]);
        }
    });
    let ans = [];
    for (let i = arr.length - 1; i >= 0 && ans.length < k; i--) {
        arr[i] && ans.push(...arr[i]);
    }
    return ans;
};

复杂度分析2

复杂度分析不是很会,不一定对,如果有错,请指正。

yetfan commented 2 years ago

思路 ummmmm 大概类似topk明天再写今天懒了=。= 调库yyds

代码

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)]

复杂度 时间 O(nlogn) 空间 O(n)

yan0327 commented 2 years ago

思路一: 先用一个data结构体来存次数和值。 遍历数组,用哈希表存次数。 遍历哈希表,将值和次数存在data数组。 对data数组排序,并将值赋值给输出数组ans

type data struct{
    num int
    times int
}
func topKFrequent(nums []int, k int) []int {
    hashmap := map[int]int{}
    for _,x := range nums{
        hashmap[x]++
    }
    out := []data{}
    for i,x := range hashmap{
        out = append(out,data{num:i,times:x})
    }
    sort.Slice(out,func(i,j int) bool{
        return out[i].times > out[j].times
    })
    ans := make([]int,k)
    for i:=0;i<k;i++{
        ans[i] = out[i].num
    }
    return ans

}

时间复杂度O(nlogn) 空间复杂度O(n)

思路二: 采用堆排序处理TOPK类型。 对于GO语言来说,要使用堆需要构建五个函数,分别是Len(),Less(),Swap(),Push(),Pop() 其中Less决定是大顶堆还是小顶堆。再最开始的 type Iheap [][2]int 其中的[2]int指的是堆中存放的数据。 这里存放一个二元组,0表示数据,1表示次数。 构建完之后其他思路同之前一样,哈希表存次数,入堆。如果堆的数量大于K则出堆【这里选用最小堆】 最后,构建一个out数组,从后往前 从堆顶拿数据,get answer!

type Iheap [][2]int
func (h Iheap) Len() int{ return len(h)}
func (h Iheap) Less(i,j int) bool{return h[i][1]<h[j][1]}
func (h Iheap) Swap(i,j int) {h[i],h[j] = h[j],h[i]}
func (h *Iheap) Push (x interface{}){
    *h = append(*h,x.([2]int))
}
func (h *Iheap) Pop () interface{}{
    out := *h
    x := out[len(out)-1]
    *h = out[:len(out)-1]
    return x
}
func topKFrequent(nums []int, k int) []int {
    hash := map[int]int{}
    for _,x:= range nums{
        hash[x]++
    }
    h := &Iheap{}
    heap.Init(h)
    for key,value := range hash{
        heap.Push(h,[2]int{key,value})
        if h.Len() > k{
            heap.Pop(h)
        }
    }
    out := make([]int,k)
    for i:=k-1;i>=0;i--{
        out[i] = heap.Pop(h).([2]int)[0]
    }
    return out
}

时间复杂度O(NlogN) 空间复杂度O(N)

BpointA commented 2 years ago

思路

桶排序

代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        from collections import defaultdict
        d=defaultdict(int)
        mx=0
        for i in nums:
            d[i]+=1
            mx=max(mx,d[i])
        res=[[] for _ in range(mx+1)]
        for key,v in list(d.items()):
            res[v].append(key)
        final=[]
        while len(final)<k and len(res)>0:
            final=final+res[-1]
            res.pop()
        return final
tian-pengfei commented 2 years ago
class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {

        vector<int>  re;
        sort(nums.begin(),nums.end());
//        count, value
        vector<tuple<int,int>> tp;
        int last_val = INT_MIN;
        int count = 0;
        for(auto & num:nums){
            if(last_val!=num){
                tp.emplace_back(count,last_val);
                count = 1;
                last_val = num;
                continue;
            }
            count++;
        }
        //情况没有考虑全
        tp.emplace_back(count,last_val);
        sort(tp.begin(),tp.end(),greater<>());

        for(int i=0;i<k;i++){
            re.emplace_back(get<1>(tp[i]));
        }
        return re;
    }
};
zwmanman commented 2 years ago

class Solution(object): def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ if k == len(nums): return nums

    dictHelper = {}

    for num in nums:
        if num not in dictHelper:
            dictHelper[num] = 1
        else:
            dictHelper[num] += 1

    return heapq.nlargest(k, dictHelper.keys(), dictHelper.get)
Bochengwan commented 2 years ago

思路

利用hashmap记录frequency,再利用heapsort得到k largest、

代码

import heapq as hp
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        a = defaultdict(int)
        for num in nums:
            a[num]+=1
        b = []
        for key in a:
            b.append((-a[key],key))
        hp.heapify(b)
        result = []
        for i in range(k):
            result.append(hp.heappop(b)[1])
        return result

复杂度分析

CodeWithIris commented 2 years ago

Question

Day20 347 https://leetcode-cn.com/problems/top-k-frequent-elements/

Note (Hash table, priority_queue)

Solution (C++)


class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
          vector<int> ans;
          unordered_map<int, int> hash;
          priority_queue<pair<int, int>> q;
          for(auto& num : nums) hash[num]++;
          for(auto& item: hash) q.push(make_pair(item.second, item.first));
          while(k--){
              ans.push_back(q.top().second);
              q.pop();
          }
          return ans;
    }
};

Complexity

rzhao010 commented 2 years ago

Thoughts

Code

    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        int[] res = new int[k];
        for (int num: nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        PriorityQueue<Integer> heap = new PriorityQueue<Integer>((a, b) -> map.get(a) - map.get(b));
        for (Integer key: map.keySet()) {
            if (heap.size() < k) {
                heap.add(key);
            } else if (map.get(key) > map.get(heap.peek())) {
                heap.remove();
                heap.add(key);
            }
        }
        int idx = k - 1;
        while (!heap.isEmpty()) {
            res[idx--] = heap.remove();
        }
        return res;
    }

Complexity

ZhangNN2018 commented 2 years ago

思路

复杂度

代码

  def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        #O(n)
        nums_dict = {}
        res = [[] for i in range(len(nums)+1)]
        for i in nums:
            nums_dict[i] =nums_dict.get(i,0)+1

        for num, times in nums_dict.items():
            res[times].append(num)

        ans = []
        for i in range(len(nums), 0, -1):
            if len(res[i]) == 0:
                continue
            ans.extend(res[i])
            if len(ans) == k:
                return ans
feifan-bai commented 2 years ago

思路

  1. 建立一个最小堆,如果堆元素<k,直接插入堆中
  2. 如果堆的元素个数等于k,则检查堆顶与当前出现次数的大小,如果堆顶更大,舍弃当前值,否则更新堆 代码
    import heapq
    class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        if len(nums) == k: return nums
        d = {}
        res = []
        for num in nums:
            if num in d:
                d[num] += 1
            else:
                d[num] = 1
        h = []
        for key in d:
            heappush(h, (d[key], key))
            if len(h) > k:
                heappop(h)
        while h:
            frq, item = heappop(h)
            res.append(item)
        return res

    复杂度分析

    • 时间复杂度:O(NlogK)
    • 空间复杂度:O(N)
Neal0408 commented 2 years ago
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)]
xj-yan commented 2 years ago
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        d = dict()
        for num in nums:
            if num not in d.keys():
                d[num] = 1
            else:
                d[num] += 1
        maxHeap = [[-freq, num] for num, freq in d.items()]
        heapq.heapify(maxHeap)
        ans = []
        for i in range(k):
            _, num = heapq.heappop(maxHeap)
            ans.append(num)
        return ans

Time Complexity: O(NlogK), Space Complexity: O(n)

zhiyuanpeng commented 2 years ago
from collections import Counter

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        if nums:
            c = Counter(nums)
            # the size of pool is k
            pool = dict()
            pool_min_val = float("inf")
            pool_min_key = 0
            for key, val in c.items():
                # add to pool until size of pool = k
                if len(pool) < k:
                    pool[key] = val
                    # update the min key and min val
                    if val < pool_min_val:
                        pool_min_val = val
                        pool_min_key = key
                # once pool is full, remove smallest one if find bigger one
                else:
                    if val > pool_min_val:
                        del pool[pool_min_key]
                        pool[key] = val
                        # update the smallest values
                        pool_min_key = min(pool, key=pool.get)
                        pool_min_val = pool[pool_min_key]
            return list(pool.keys())
        else:
            return []

time O(N), space O(N)

AlduinLeung commented 2 years ago

用hashmap做最简单,主要是熟练hashmap的api使用,最后用set转成没有重复元素的数组,排序截取即可

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function(nums, k) {
    let map = new Map();
    nums.map((item)=>{
        if(map.has(item)){
            map.set(item,map.get(item)+1);
        }else{
            map.set(item,1);
        }
    });

    let arr = [...new Set(nums)];
    console.log(arr);
    arr.sort((a,b)=>map.get(b)-map.get(a));
    // reverse order by frequency
    return arr.splice(0,k);

};

时间复杂度应该是排序算法的时间复杂度,空间复杂度O(N)

YuyingLiu2021 commented 2 years ago
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:       
        #Solution1:
        #先把每个num遍历一遍,用字典。
        #然后排序(将字典转化为列表l,对列表l按照频次进行排序(利用匿名函数;倒序)。
        #再把前k个取出来。
        dict= {}
        for i in range(len(nums)):
            if nums[i] not in dict:
                dict[nums[i]] = 1
            if nums[i] in dict:
                dict[nums[i]] += 1                
        l = list(dict.items())
        l.sort(key = lambda x : x[1], reverse = True)
        res=[]
        for i in range(k):
            res.append(l[i][0])  
        return res

#         #Solution 2 直接排序
#         #记录每个数字出现的次数
#         #返回次数最高的前k个数
#         #时间复杂度O(NlogN)
#         #空间复杂度O(N)
#         count = collections.Counter(nums)
#         return [item[0] for item in count.most_common(k)]

#         #solution 3 堆
#         #记录每个数字出现的次数
#         #把这个数和出现的次数放在heap中
#         #返回heap中前k个对大元素
#         #时间复杂度O(NlogN)
#         #空间复杂度O(N)
#         count = collections.Counter(nums)
#         heap = [(val, key) for key, val in count.items()]
#         return [item[1] for item in heapq.nlargest(k, heap)]
RocJeMaintiendrai commented 2 years ago
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int num : nums) {
            if(map.containsKey(num)) {
                map.put(num, map.get(num) + 1);
            } else {
                map.put(num, 1);
            }
        }
        Queue<Integer> queue = new PriorityQueue<>((a, b) -> map.get(a) - map.get(b));
        for(int num : map.keySet()) {
            if(queue.size() < k) {
                queue.offer(num);
            } else if(map.get(num) > map.get(queue.peek())) {
                queue.poll();
                queue.offer(num);
            }
        }
        int[] res = new int[k];
        for(int i = 0; i < k; i++) {
            res[i] = queue.poll();
        }
        return res;
    }
}

复杂度分析

laofuWF commented 2 years ago
# solution 2: use min heap
# build counter
# heappush (freq, num)
# heappop if curr heap length is greater than k 
# (aka removed number that has the lowest freq)
# (aka keep a heap list with elements with max freq so far)

# time: O(NlogK)
# space: o(N)

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        counter = defaultdict(int)
        min_heap = []
        for num in nums:
            counter[num] += 1

        for num in counter.keys():
            # min heap of top k items
            heapq.heappush(min_heap, (counter[num], num))
            if len(min_heap) > k:
                heapq.heappop(min_heap)

        res = []
        for freq, num in min_heap:
            res.append(num)

        return res
zhangzz2015 commented 2 years ago

思路

关键点

代码

C++ Code:


class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {

        unordered_map<int, int> record; 
        for(int i=0; i< nums.size(); i++)
        {
            record[nums[i]]++; 
        }
        auto comp = [](pair<int,int>& node1, pair<int,int>&node2)
        {
           if(node1.second ==node2.second) return node1.first < node2.first; 
            return node1.second > node2.second; 
        }; 
        priority_queue<pair<int,int>, vector<pair<int,int>>, decltype(comp)> pq(comp); 
        for(auto it = record.begin(); it!=record.end(); it++)
        {
            if(pq.size()<k)
            {
                pq.push((*it)); 
            }
            else
            {
                if((*it).second>pq.top().second)
                {
                    pq.pop(); 
                    pq.push((*it)); 
                }
            }
        }

        vector<int> ret; 
        while(pq.size())
        {
            ret.push_back(pq.top().first); 
            pq.pop(); 
        }

        return ret; 
    }
};
ZacheryCao commented 2 years ago

Idea

Heap + HashTable. First use hash table to record each unique element's frequency. Then, scan over the hash table. If current heap length smaller than k, push [current element frequency, current element] in to the heap. Otherwise, if current element's frequency larger than k, pop out first pair in heap, and push current pair to heap.

Code

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        count = collections.Counter(nums)
        heap= []
        for i in count:
            if len(heap) == k and count[i] > heap[0][0]:
                heapq.heappop(heap)
                heapq.heappush(heap,[count[i],i])
            elif len(heap)<k:
                heapq.heappush(heap,[count[i],i])
        return [i[1] for i in heap]

Complexity:

Time: O(NlogK) Space: O(N)

freesan44 commented 2 years ago

思路

关键点

代码

Python3 Code:


class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        from collections import Counter
        counter = Counter(nums).most_common(k)
        # print([key for key,val in counter])
        return [key for key,val in counter]
Toms-BigData commented 2 years ago

【Day 20】347. 前 K 个高频元素

思路

遍历数组,将每个数字出现个数存入map中,构建一个新结构体,参数是map的key和value,将map中的元素出入结构体列表中,通过value大小排序,返回前K个

golang代码

type newMap struct {
    key int
    value int
}
type newMapSlice []newMap

func (s newMapSlice) Len() int {
    return len(s)
}
func (s newMapSlice) Swap(i, j int) {
    s[i], s[j] = s[j], s[i]
}
func (s newMapSlice) Less(i, j int) bool {
    return s[i].value>s[j].value
}
func topKFrequent(nums []int, k int) []int {
    hashmap := map[int]int{}
    for _,num := range nums{
        hashmap[num] += 1
    }
    newmapslice := newMapSlice{}
    ans := make([]int, 0)
    for key,value := range hashmap{
        newmap := newMap{key,value}
        newmapslice = append(newmapslice, newmap)
    }
    sort.Sort(newmapslice)
    for i:= 0;i<k;i++{
        ans = append(ans, newmapslice[i].key)
    }
    return ans
}

复杂度

时间:O(n) 空间:O(n)

caohaha commented 2 years ago

思路

使用哈希表统计频率,使用堆找出前k个高频出现的元素

C++ code

class Solution 
{
public:
    vector<int> topKFrequent(vector<int>& nums, int k) 
    {
        vector<int> res;
        unordered_map<int,int> m;
        priority_queue<pair<int,int>> q;
        for(int i=0;i<nums.size();i++)
            m[nums[i]] ++;
        for(auto p : m)
            q.push(pair<int,int> (p.second,p.first));
        while(k--)
        {
            res.push_back(q.top().second);
            q.pop();
        }
        return res;
    }
};

复杂度分析

zjsuper commented 2 years ago

class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: dic = defaultdict(int) for i in nums: dic[i] += 1

print(dic)

    dic = sorted(dic, key=dic.get, reverse=True)
    #print(dic)
    ans = []
    kk = 0
    for key in dic:
        #print(key)
        ans.append(key)
        kk += 1
        if kk == k:
            break
    return ans
Serena9 commented 2 years ago

代码

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        count = collections.Counter(nums)
        heap = []
        for key, val in count.items():
            if len(heap) >= k:
                if val > heap[0][0]:
                    heapq.heapreplace(heap, (val, key))
            else:
                heapq.heappush(heap, (val, key))
        return [item[1] for item in heap]

复杂度分析

时间复杂度:O(nlogk)

空间复杂度:O(n)

nonevsnull commented 2 years ago

思路

//s6

代码

//s6 heap
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer, Integer> map = new HashMap<>();

        for(int num: nums){
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        PriorityQueue<int[]> heap = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);

        for(int key: map.keySet()){
            if(heap.size() == k && heap.peek()[1] < map.get(key)) {
                heap.poll();
            }
            if(heap.size() < k){
                heap.add(new int[]{key, map.get(key)});
            }
        }

        int[] res = new int[k];

        for(int i = 0;i < res.length;i++){
            res[i] = heap.poll()[0];
        }
        return res;
    }
}

//s6 bucket
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer, Integer> map = new HashMap<>();

        for(int num: nums){
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        List<Integer>[] sum = new ArrayList[nums.length];

        for(int key: map.keySet()){
            int count = map.get(key);
            if(sum[count - 1] == null) {
                sum[count - 1] = new ArrayList<>();
            }
            sum[count - 1].add(key);
        }

        int[] res = new int[k];
        int index = 0;
        for(int i = sum.length - 1;i >= 0;i--){
            if(index == k){
                return res;
            } else if(sum[i] != null) {
                for(int j = 0;j < sum[i].size();j++){
                    res[index] = sum[i].get(j);
                    index++;
                }
            }
        }

        return res;
    }
}

复杂度

//heap time: O(NlogN),每次存入logN,存N次; space:heap所需的空间O(D), D是不同的元素的个数,最坏为O(N)

//hashmap+ArrayList[] time: O(N) space: O(N),比起上一种方法,多用了array of list,但并未影响最终复杂度;

ivangin commented 2 years ago

CODE :


public List<Integer> topKFrequent2(int[] nums, int k) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        PriorityQueue<Map.Entry<Integer, Integer>> maxHeap =
                new PriorityQueue<>((a, b) -> (b.getValue() - a.getValue()));
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            maxHeap.add(entry);
        }

        List<Integer> res = new ArrayList<>();
        while (res.size() < k) {  // O(klogn)
            Map.Entry<Integer, Integer> entry = maxHeap.poll();
            res.add(entry.getKey());
        }
        return res;
    }
yuetong3yu commented 2 years ago

先用 哈希表 将数组中出现的元素次数存下来。

然后对 哈希表 进行一个排序,在取排序 前 k 个数即可。

var topKFrequent = function (nums, k) {
  const map = {}
  nums.forEach((i) => {
    if (map[i] === undefined) {
      map[i] = 1
    } else {
      map[i] += 1
    }
  })
  const entries = Object.entries(map)
  const sorted_entries = entries.sort((a, b) => b[1] - a[1])
  const res = sorted_entries.map((i) => i[0])
  return res.slice(0, k)
}
iambigchen commented 2 years ago

思路

用map记录每个值出现过的频率,在对map的key进行排序,排序依据是通过value的大小

关键点

代码

JavaScript Code:


/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function(nums, k) {
    let map = {}
    let res = []
    for(let i = 0; i<nums.length; i++) {
        map[[nums[i]]] = map[[nums[i]]] ? map[[nums[i]]] + 1 : 1
    }
    let keys = Object.keys(map)
    keys.sort((a, b) => map[b] - map[a])
    while(k > 0) {
        let key = keys.shift()
        res.push(key)
        k--
    }
    return res
};

复杂度分析

令 n 为数组长度。

wenlong201807 commented 2 years ago

代码块


var topKFrequent = function (nums, k) {
  let map = new Map()
  let 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)
};

时间复杂度和空间复杂度

stackvoid commented 2 years ago

思路

思路比较清晰,先用HashMap轮询一遍,找到离散的每个数字对应出现的频率。 然后把 EntrySet 拿出来从高往低排序。 获取前K个Entry.Key 输出即可。

代码

import java.util.*;

//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        LinkedHashMap<Integer, Integer> linkedHashMap = new LinkedHashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (linkedHashMap.containsKey(nums[i])) {
                linkedHashMap.put(nums[i], linkedHashMap.get(nums[i]) + 1);
            } else {
                linkedHashMap.put(nums[i], 1);
            }
        }

        List<Map.Entry<Integer, Integer>> list = new ArrayList<>(linkedHashMap.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {
            @Override
            public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
                return o2.getValue() - o1.getValue();
            }
        });

        int[] ans = new int[k];
        for (int i = 0; i < list.size() && i < k; i++) {
            ans[i] = list.get(i).getKey();
        }
        return ans;
    }
}
//leetcode submit region end(Prohibit modification and deletion)

算法复杂度分析

haixiaolu commented 2 years ago

思路

桶排序 + 哈希表

代码 / Python


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 

复杂度分析

suukii commented 2 years ago

Link to LeetCode Problem

S1: 哈希表

直观思路,遍历数组统计数字出现的次数,按次数排序后输出前 k 个数字,可以使用哈希表来记录。

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        map<int, int> count;
        for (int n : nums)
          count[n]++;

        // sort map by value
        vector<pair<int, int>> freq(count.begin(), count.end());
        sort(freq.begin(), freq.end(), [](pair<int, int>& a, pair<int, int>& b) { return a.second > b.second; });

        vector<int> res;
        res.reserve(k);
        int i = 0;
        while (i < k) {
            res.emplace_back(freq[i++].first);
        }
        return res;
    }
};
/**
 * @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]++;
    }
    // 对次数进行排序然后输出前 k 个
    return Object.entries(map)
        .sort((a, b) => b[1] - a[1])
        .slice(0, k)
        .map(a => a[0]);
};

S2: 堆

看到 求前 k 个 这样的描述自然会联想到用 来进行排序。

大顶堆

class Solution {
public:
    using Pair = pair<int, int>;
    vector<int> topKFrequent(vector<int>& nums, int k) {
        map<int, int> count;
        for (int n : nums)
          count[n]++;

        // 大顶堆
        auto cmp = [](Pair a, Pair b) { return a.second < b.second; };
        priority_queue<Pair, vector<Pair>, decltype(cmp)> pq(count.begin(), count.end(), cmp);

        vector<int> res;
        res.reserve(k);
        int i = 0;
        while (i++ < k) {
            res.emplace_back(pq.top().first);
            pq.pop();
        }
        return res;
    }
};
/**
 * @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 maxHeap = new MaxHeap(Object.entries(map), function comparator(
        inserted,
        compared,
    ) {
        return inserted[1] < compared[1];
    });
    // 输出前 k 个
    const res = [];
    while (k-- > 0) {
        res.push(maxHeap.pop()[0]);
    }
    return res;
};

// *******************************************

class Heap {
    constructor(list = [], comparator) {
        this.list = list;

        if (typeof comparator != 'function') {
            this.comparator = function comparator(inserted, compared) {
                return inserted < compared;
            };
        } else {
            this.comparator = comparator;
        }

        this.init();
    }

    init() {
        const size = this.size();
        for (let i = Math.floor(size / 2) - 1; i >= 0; i--) {
            this.heapify(this.list, size, i);
        }
    }

    insert(n) {
        this.list.push(n);
        const size = this.size();
        for (let i = Math.floor(size / 2) - 1; i >= 0; i--) {
            this.heapify(this.list, size, i);
        }
    }

    peek() {
        return this.list[0];
    }

    pop() {
        const last = this.list.pop();
        if (this.size() === 0) return last;
        const returnItem = this.list[0];
        this.list[0] = last;
        this.heapify(this.list, this.size(), 0);
        return returnItem;
    }

    size() {
        return this.list.length;
    }
}

class MaxHeap extends Heap {
    constructor(list, comparator) {
        super(list, comparator);
    }

    heapify(arr, size, i) {
        let largest = i;
        const left = Math.floor(i * 2 + 1);
        const right = Math.floor(i * 2 + 2);

        if (left < size && this.comparator(arr[largest], arr[left]))
            largest = left;
        if (right < size && this.comparator(arr[largest], arr[right]))
            largest = right;

        if (largest !== i) {
            [arr[largest], arr[i]] = [arr[i], arr[largest]];
            this.heapify(arr, size, largest);
        }
    }
}

小顶堆

class Solution {
public:
    using Pair = pair<int, int>;
    vector<int> topKFrequent(vector<int>& nums, int k) {
        map<int, int> count;
        for (int n : nums)
          count[n]++;

        // 小顶堆
        auto cmp = [](Pair a, Pair b) { return a.second > b.second; };
        priority_queue<Pair, vector<Pair>, decltype(cmp)> pq(cmp);
        for (Pair p : count) {
            if (pq.size() < k) {
                pq.push(p);
            } else if (pq.size() == k && p.second > pq.top().second) {
                pq.pop();
                pq.push(p);
            }
        }

        vector<int> res;
        res.reserve(k);
        int i = k;
        while (--i >= 0) {
            res.emplace(res.begin(), pq.top().first);
            pq.pop();
        }
        return res;
    }
};
/**
 * @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 minHeap = new MinHeap([], function comparator(inserted, compared) {
        return inserted[1] > compared[1];
    });

    // 维护一个大小为 k 的小顶堆,堆元素格式是:[数字,次数],按次数排序
    Object.entries(map).forEach(([num, times]) => {
        const [, minTimes] = minHeap.peek() || [, 0];
        // 小顶堆大小还没达到 k,继续插入新元素
        if (minHeap.size() < k) {
            minHeap.insert([num, times]);
        }

        // 小顶堆大小为 k,如果新元素次数大于堆顶,弹出堆顶,插入新元素
        // 否则就不用管这个元素了
        else if (minHeap.size() === k && times > minTimes) {
            minHeap.pop();
            minHeap.insert([num, times]);
        }
    });

    // 反序输出小顶堆中的所有元素
    const res = Array(k);
    while (k-- > 0) {
        res[k] = minHeap.pop()[0];
    }
    return res;
};

// *************************************

class MinHeap extends Heap {
    constructor(list, comparator) {
        if (typeof comparator != 'function') {
            comparator = function comparator(inserted, compared) {
                return inserted > compared;
            };
        }
        super(list, comparator);
    }

    heapify(arr, size, i) {
        let smallest = i;
        const left = Math.floor(i * 2 + 1);
        const right = Math.floor(i * 2 + 2);
        if (left < size && this.comparator(arr[smallest], arr[left]))
            smallest = left;
        if (right < size && this.comparator(arr[smallest], arr[right]))
            smallest = right;

        if (smallest !== i) {
            [arr[smallest], arr[i]] = [arr[i], arr[smallest]];
            this.heapify(arr, size, smallest);
        }
    }
}

大顶堆

顶堆

S3: 快速选择

既然只是求前 k 个高频数字,便可不必对数组进行完全排序,局部排序算法 快速选择 - Quick Select 就是为这道题而生的。

虽然快速选择的目的只是找到第 k 大(小) 数字,但看结果我们也把前 k 大(小) 数字都归拢到了数组开头,且本题对返回结果的顺序不做要求,所以当我们用快速选择找到第 k 大数字时,只需要把数组此时的前 k 个数字返回即可。

/**
 * @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,
        );
}
shamworld commented 2 years ago
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)
    })

    // 如果元素数量小于等于 k
    if(map.size <= k) {
        return [...map.keys()]
    }

    return bucketSort(map, k)
};
// 桶排序
let bucketSort = (map, k) => {
    let arr = [], res = []
    map.forEach((value, key) => {
        // 利用映射关系(出现频率作为下标)将数据分配到各个桶中
        if(!arr[value]) {
            arr[value] = [key]
        } else {
            arr[value].push(key)
        }
    })
    // 倒序遍历获取出现频率最大的前k个数
    for(let i = arr.length - 1;i >= 0 && res.length < k;i--){
        if(arr[i]) {
            res.push(...arr[i])
        }
    }
    return res
}
hdyhdy commented 2 years ago

思路: 哈希表记录出现次数,利用数组将次数与数值记录,再利用排序函数将数据进行排序,最后输出前K个。

func topKFrequent(nums []int, k int) []int {
    hashmap := map[int]int{}
    for _,x := range nums {
        hashmap[x] ++
    }
    out := []data {}
    for i,x := range hashmap{
        out = append(out,data{num:i,time:x})
    }
    sort.Slice(out,func(i,j int) bool {
        return out[i].time > out[j].time
    })
    ans := make([]int,k)
    for i:=0;i<k;i++{
        ans[i] = out[i].num
    }
    return ans
}

type data struct {
    num int
    time int
}

时间复杂度:nlogn 空间:n

732837590 commented 2 years ago

class Solution { public int[] topKFrequent(int[] nums, int k) { / 出现频次前k高的元素,用桶排序的知识来求解, 我们把数出现的频次作为每个桶的标签,然后把出现相同频次的数字放入到对应的桶中, 而桶中的标签范围是根据数可能出现的最大次数决定的,接着初始化的时候标签就已经 按从小到大的顺序排好无需我们再次比较,直接到过来从标签最大的桶反向遍历每个桶, 从倒数第一个不为空的桶开始算,把里面的数取出来,就是频次出现最高的k个数了。 /

    //定义一个hashmap来初始化每个数出现的频次,key是数值,value是频次
    HashMap<Integer,Integer> hashMap = new HashMap<>();
    //返回的结果集开辟空间
    int[] result = new int[k];

    for(int num : nums){
        hashMap.put(num,hashMap.getOrDefault(num,0) + 1);
    } 

    List<Integer>[] list = new ArrayList[nums.length + 1];
    //让数字key出现的频次value作为桶的索引index
    for(int num : hashMap.keySet()){
        int i = hashMap.get(num);
        //如果当前桶中还未建立对应的桶表我们就初始化一个
        if(list[i] == null){
            list[i] = new ArrayList<>();
        }
        list[i].add(num);
    }

    int i = 0, t , j;
    //从频次最高的第一个不为空的桶开始反向取值
    for(t = nums.length; t > 0; --t){
        if(list[t] != null){
            for(j = 0; j < list[t].size() && i < k; ++j){
                result[i++] = list[t].get(j);
            }
        }
    }
    return result;
}

}

Flower-F commented 2 years ago

解题思路

哈希表 + 桶排序

代码

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function (nums, k) {
    // 哈希
    const map = new Map();
    let maxSize = 0;
    nums.forEach(num => {
        if (!map.has(num)) {
            map.set(num, 1);
            maxSize = Math.max(1, maxSize);
        } else {
            const count = map.get(num) + 1;
            map.set(num, count);
            maxSize = Math.max(count, maxSize);
        }
    });

    // 桶排
    const bucket = new Array(maxSize + 1);
    map.forEach((value, key) => {
        if (bucket[value] === undefined) {
            bucket[value] = [];
        }
        bucket[value].push(key);
    })

    // 答案
    const res = [];
    for (let i = maxSize; i >= 0 && res.length < k; i--) {
        if (bucket[i] === undefined) {
            continue;
        }
        res.push(...bucket[i]);
    }

    return res;
};

复杂度

时间:O(N) 空间:O(N)

Yachen-Guo commented 2 years ago

思路

根据频率构建hashmap,而后采用heap, 在minheap中比较堆顶元素与新入队元素freq的大小,遍历heap出队

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<Integer,Integer>();
         for(int i = 0; i < nums.length; i++){
            map.put(nums[i],map.getOrDefault(nums[i],0)+1);
        }
        PriorityQueue<int[]> pq = new PriorityQueue<int[]>(new Comparator<int[]>(){
            public int compare(int[] m, int[]n){
                return m[1]-n[1];
            }
        });

        for(Map.Entry<Integer,Integer> entry : map.entrySet()){
            int num = entry.getKey();
            int freq = entry.getValue();
            if(pq.size() == k){
                if(pq.peek()[1]<freq){
                pq.poll();
                pq.offer(new int[]{num,freq});
            }}
            else{
                pq.offer(new int[]{num,freq});
            }
        }

        int[] res = new int[k];
        int cnt = 0;
        while(!pq.isEmpty()){
            res[cnt] = pq.poll()[0];
            cnt++;
        }
        return res;
    }
}
uniqlell commented 2 years ago

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); } return map.entrySet() .stream() .sorted((m1, m2) -> m2.getValue() - m1.getValue()) .limit(k) .mapToInt(Map.Entry::getKey) .toArray(); } }

biaohuazhou commented 2 years ago

思路

先把每个数字和数字对应的次数 放到栈中保存 然后再创建一个 int[]的堆 int[] 第一个元素记录数字值 第二个元素记录改值出现的次数 然后挨个放到堆里面 堆的大小为K 判断当前的次数和堆顶的次数大小

代码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
          map.put(num,map.getOrDefault(num,0)+1);
        }
        //int[] 第一个元素记录数字值  第二个元素记录改值出现的次数
        PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
            @Override
            //从大到小排序
            public int compare(int[] o1, int[] o2) {
                return o1[1]-o2[1];
            }
        });

        //
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            int num=entry.getKey(), count=entry.getValue();
            if (queue.size()==k){
                if (queue.peek()[1]<count){
                    //如果堆达到了k个  就比较当前的数组次数是否大于堆顶的数组的次数
                    queue.poll();
                    queue.offer(new int[]{num,count});
                }
            }else {
                queue.offer(new int[]{num,count});
            }
        }
        int[] ans=new int[k];
        for (int i = 0; i <k ; i++) {
            ans[i]=queue.poll()[0];
        }
        return ans;

    }
}

复杂度分析 时间复杂度: O(nlog(k)) n为数组长度 放去哈希表需要O(n) 。 然后遍历 int[]数组 最多有N个,再对堆排序 时间为O(longk) ,总共为O(nlog(k))。 空间复杂度:O(n)为哈希表所需要的大小 O(k)为堆的大小 和最后返回答案的大小,所以总的复杂度为O(n)。

lilililisa1998 commented 2 years ago

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

LannyX commented 2 years ago

思路

Hash Map + 小顶堆

代码

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);
        }
        Queue<int[]> pq = new PriorityQueue<>(
            (o1, o2) -> o1[1] - o2[1]
        );
        for(Integer n : map.keySet()){
            pq.offer(new int[]{n, map.get(n)});
            if(pq.size() > k){
                pq.poll();
            }
        }
        int[] ans = new int[k];
        for(int i = k - 1; i >= 0; i--){
            ans[i] = pq.poll()[0];
        }
        return ans;
    }
}

复杂度分析

chakochako commented 2 years ago
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)]
Grendelta commented 2 years ago

思路

进行堆排序,记录每个数字出现的次数,把数字和对应的出现次数放到堆中(小顶堆),如果堆已满(大小>=k)且当前数的次数比堆顶大,用当前元素替换堆顶元素,最后返回堆中的数字部分。

代码

class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: count = collections.Counter(nums) heap = [] for key, val in count.items(): if len(heap) >= k: if val > heap[0][0]: heapq.heapreplace(heap, (val, key)) else: heapq.heappush(heap, (val, key)) return [item[1] for item in heap]

复杂度

时间复杂度 O(NlogK)

空间复杂度 O(N)

declan92 commented 2 years ago

思路:看见频率第一反应使用hash表求解
步骤:

  1. 遍历数组,使用哈希表保存,key表示数组值,value表示出现次数;
  2. 对Map按照value排序;
  3. 返回前K个元素; 注意:
    同一个元素不要记录多次
    java
    class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap();
        int[] ans = new int[k];
        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);
            }
        }
        //对map排序,使用value大小降序排序
        List<Map.Entry<Integer,Integer>> list = new ArrayList(map.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<Integer,Integer>>(){
            @Override
            public int compare(Map.Entry<Integer,Integer> o1,Map.Entry<Integer,Integer> o2){
                return  o2.getValue() - o1.getValue();
            }
        });
        for(int i = 0;i<k;i++){
            ans[i] = list.get(i).getKey();
        }
        return ans;
    }
    }

    时间:O(nlogn),瓶颈在排序;
    空间:O(n),n为数组长度;

tongxw commented 2 years ago

思路

利用快速排序的思路,按频率从大到小快速排序,如果发现前半区间恰好就是top k的话,由于top k不要求有序,所以可以直接返回结果。

代码

class Solution {
    Map<Integer, Integer> freq;
    public int[] topKFrequent(int[] nums, int k) {
        freq = new HashMap<>();
        for (int num : nums) {
            freq.put(num, freq.getOrDefault(num, 0) + 1);
        }

        int[] numsNoDupe = new ArrayList<>(freq.keySet()).stream().mapToInt(i -> i).toArray();
        return quickSelect(numsNoDupe, 0, numsNoDupe.length - 1, k);
    }

    private int[] quickSelect(int[] nums, int start, int end, int k) {
        if (start >= end) {
            return Arrays.copyOf(nums, k);
        }

        int l = start;
        int r = end;
        int pivot = freq.get(nums[l]);
        while (l <= r) {
            while (freq.get(nums[l]) > pivot) {
                l++;
            }
            while (freq.get(nums[r]) < pivot) {
                r--;
            }

            if (l <= r) {
                int temp = nums[l];
                nums[l] = nums[r];
                nums[r] = temp;
                l++;
                r--;
            }
        }

        // [0...r] [k] [l...n-1]
        // [0...r][l...n-1]
        if (r + 1 == k) {
            return Arrays.copyOf(nums, k);
        } else if (k > r) {
            return quickSelect(nums, l, end, k);
        } else {
            return quickSelect(nums, start, r, k);
        }
    }
}

SC: O(N) 平均复杂度 TC: O(N) 哈希表

cszys888 commented 2 years ago
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        from collections import Counter
        bucket = [[] for _ in range(len(nums)+1)]
        count = Counter(nums)
        for num, freq in count.items():
            bucket[freq].append(num)
        result = []
        for freq in range(len(bucket)-1, -1, -1):
            for element in bucket[freq]:
                result.append(element)
                if len(result)==k:
                    return result

time complexity: O(N) space complexity: O(N)

CodingProgrammer commented 2 years ago

思路

  1. 利用Map统计次数
  2. 利用优先级队列根据出现次数排序,只需出现频次最高的k个存在优先级队列中
  3. 从优先级队列中将结果存到数组中

代码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        int[] res = new int[k];

        // 统计次数
        Map<Integer, Integer> counter = new HashMap<>();
        for (int num : nums) {
            counter.put(num, counter.getOrDefault(num, 0) + 1);
        }

        // 通过优先级队列,保持最高频次的数字 Integer[0]-次数 Integer[1]-数字
        PriorityQueue<Integer[]> mostK = new PriorityQueue(k, new Comparator<Integer[]>() {
            @Override
            public int compare(Integer[] i1, Integer[] i2) {
                return i1[0] - i2[0];
            }
        });

        for (Integer key : counter.keySet()) {
            Integer times = counter.get(key);
            if (mostK.size() < k) {
                mostK.offer(new Integer[]{times, key});
            } else {
                if (times > mostK.peek()[0]) {
                    mostK.poll();
                    mostK.offer(new Integer[]{times, key});
                }
            }
        }

        // 从优先级队列中取出相应的数字
        int index = 0;
        while (!mostK.isEmpty()) {
            res[index++] = mostK.poll()[1];
        }

        return res;
    }
}

复杂度

taojin1992 commented 2 years ago
val-freq map
minHeap

Time: O(nums.length) + O(number of entries) * logk + klogk
Space: O(number of entries) + O(k)

Code:


class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> valFreq = new HashMap<>();
        for (int num : nums) {
            valFreq.put(num, valFreq.getOrDefault(num, 0) + 1);
        }
        PriorityQueue<Map.Entry<Integer, Integer>> minHeap = new PriorityQueue<>((a, b) -> (a.getValue() - b.getValue()));
        for (Map.Entry<Integer, Integer> entry : valFreq.entrySet()) {
            minHeap.offer(entry);
            if (minHeap.size() > k) {
                minHeap.poll();
            }
        }
        int[] topK = new int[k];
        int curIndex = 0;
        while (!minHeap.isEmpty()) {
            topK[curIndex++] = minHeap.poll().getKey();
        }
        return topK;
    }
}
ACcentuaLtor commented 2 years ago

Python,先字典遍历求元素出现频率,然后 sorted排序 时间复杂度O(nlogn),空间复杂度O(n)

 def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        dict1 = {}
        for i in range(len(nums)):
            if nums[i] not in dict1:
                dict1[nums[i]] = 1
            else:
                dict1[nums[i]] += 1
        dict1_sorted_values = sorted(dict1.items(),key = lambda x:x[1],reverse = True)
        res = []
        for i in range(k):
            res.append(dict1_sorted_values[i][0])
        return res