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

91 天学算法第五期打卡
55 stars 14 forks source link

【Day 20 】2021-09-29 - 347. 前 K 个高频元素 #35

Open azl397985856 opened 3 years ago

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

HackBL commented 3 years ago
Tomtao626 commented 3 years ago

思路

yanglr commented 3 years ago

思路

堆排序 + 哈希表

topK问题, 容易想到使用优先队列(堆排序)。

代码

实现语言: C++

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        vector<int> res;
        unordered_map<int, int> dict; // 映射: value -> count
        for (auto num : nums)
        {
            if (dict.find(num) == dict.end()) dict[num] = 0;
            else dict[num]++;
        }
        auto cmp = [](pair<int, int> p1, pair<int, int> p2)
        {
            return p1.second < p2.second;  /* 大顶堆 */
        };

        priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> q(cmp);
        for (auto kvp : dict) q.push(kvp);
        while (k > 0)
        {
            res.push_back(q.top().first);
            q.pop();

            k--;
        }

        return res;
    }
};

复杂度分析

st2yang commented 3 years ago

思路

代码

复杂度

BpointA commented 3 years ago

思路

暴力解哈希表+排序,时间复杂度为nlogn,采用堆之后达到进阶要求。

Python3代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        from collections import defaultdict
        import heapq
        d=defaultdict(int)
        for i in nums:
            d[i]+=1
        kv=list(d.items())
        res=[]
        for i in range(k):
            heapq.heappush(res,[kv[i][1],kv[i][0]])

        for j in range(k,len(kv)):
            k,v=kv[j]
            if v>res[0][0]:
                heapq.heappop(res)
                heapq.heappush(res,[kv[j][1],kv[j][0]])

        final=[i[1] for i in res]
        return final

复杂度

时间复杂度:O(nlogk),堆排序

空间复杂度:O(n),哈希表长度

附录

暴力解法。

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        from collections import defaultdict
        d=defaultdict(int)
        for i in nums:
            d[i]+=1
        r=sorted(d.items(),key=lambda x:-x[1])
        res=[]
        for i in range(k):
            res.append(r[i][0])
        return res      
BreezePython commented 3 years ago

思路

哈希表+排序

代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        dic = Counter(nums)
        return sorted(dic.keys(),key = lambda x:-dic[x])[:k]

复杂度:

CoreJa commented 3 years ago

思路

只想到了用哈希表然后排序的方法,之后学习一下堆排的写法

代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        d = {}
        for num in nums:
            if num not in d:
                d[num] = 1
            else:
                d[num] += 1
        t: List[Tuple] = sorted(d.items(), key=lambda x: x[1], reverse=True)
        return [i[0] for i in t[:k]]
Bochengwan commented 3 years ago

思路

使用hashmap存frequency,O(N).

然后利用heap得到topk的element,O(KLOGN)

代码

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

复杂度分析

thinkfurther commented 3 years ago

思路

用dict记录每一个数的频率,然后排序

代码

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

        sorted_dict = sorted(count_dict.items(), key = lambda x:x[1],reverse = True)
        result = []

        for i in range(k):
            result.append(sorted_dict[i][0])
        return result

复杂度

时间复杂度 :O(N*logN)

空间复杂度:O(N)

harleyszhang commented 3 years ago

解题思路

哈希表 unordered_map + 最小堆 priority_queue 的方法(C++)

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;
        // 创建 map,map的键是数组元素,键值是数组元素出现次数
        for(auto num: nums){
            map[num]++;
        }

        // 定义一个小顶堆,并维持大小为 k
        priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison > heap; // 小顶堆,堆顶为最小值
        for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
            heap.push(*it);
            if(heap.size() > k) heap.pop(); // 弹出堆顶元素,即最小元素
        }
        // heap 元素倒序输出到数组
        vector<int> ret(k);
        for (int i=k-1; i>=0; i--){
            ret[i] = heap.top().first;
            heap.pop();
        }
        return ret;
    }
};
Mahalasu commented 3 years ago

思路

priority queue + hashmap

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        if k == len(nums):
            return nums

        count = {}
        for item in nums:
            if item not in count:
                count[item] = (0, item)
            count[item] = (count[item][0] + 1, item)

        heap = []
        for value in count.values():
            heapq.heappush(heap, value)
            if len(heap) > k:
                heapq.heappop(heap)

        ans = []
        for i in range(k):
            ans.append(heapq.heappop(heap)[1])

        return ans

T: O(nlogk) S: O(n + k)

yachtcoder commented 3 years ago

The power of Counter. Time: O(nlgk) because most_common use a heap of size k to find the most frequent k items. Space: 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)]
kidexp commented 3 years ago

thoughts

先拿到nums里面每个num的count

然后把他放到最大queue里面

然后pop k次 放进results

code

import heapq
from collections import Counter

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        """
        heap solution
        """
        num_count_dict = Counter(nums)
        num_count_heap = [(-count, num) for num, count in num_count_dict.items()]
        heapq.heapify(num_count_heap)
        result = []
        for _ in range(k):
            result.append(heapq.heappop(num_count_heap)[1])
        return result

complexity

time O(klgn)

space O(n)

SunnyYuJF commented 3 years ago

思路

Heap + Counter

代码 Python

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        Counter = collections.Counter(nums)  #O(N)
        if len(Counter)<=k:
            return Counter.keys()
        heap=[]
        for key,value in Counter.items(): #O(NlogK)
            heapq.heappush(heap,(value,key))
            if len(heap)>k:
                heapq.heappop(heap)

        return [key for value,key in heap]

复杂度分析

时间复杂度:O(NlogK)
空间复杂度: O(N+K)

florenzliu commented 3 years ago

Explanation

Python

# Approach 1
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        result = []
        d = defaultdict(int)
        for n in nums:
            d[n] += 1
        for i in sorted(d.items(), key=lambda item: item[1], reverse=True):
            if k == 0:
                return result
            result.append(i[0])
            k -= 1
        return result

# Approach 2

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        if k == len(nums):
            return nums
        count = Counter(nums)
        return heapq.nlargest(k, count.keys(), key=count.get)

Complexity

Approach 1:

Approach 2:

tongxw commented 3 years ago

思路

哈希表计数,根据计数大小,对哈希表的keySet(所有不同数字)排序后输出前k个元素

代码

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

    return [...counters.keys()].sort((n1, n2) => {
      return counters.get(n2) - counters.get(n1);
    }).slice(0, k);
};
nonevsnull commented 3 years ago

思路

AC

代码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Arrays.sort(nums);

        int count = 1;

        PriorityQueue<int[]> heap = new PriorityQueue<>((o1, o2)->o2[1] - o1[1]);
        for(int i = 0;i < nums.length;i++){
            if(i < nums.length - 1 && nums[i] == nums[i+1]){
                count++;
            } else {
                heap.add(new int[]{nums[i], count});
                count = 1;
            }
        }
        int[] res = new int[k];

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

复杂度

time: 排序,O(NlogN),遍历一次求count,O(N),弹出topK,O(KlogD), D是不同的元素的个数,最坏为O(KlogN);总的复杂度取最高O(NlogN); space:heap所需的空间O(D), D是不同的元素的个数,最坏为O(N)

cicihou commented 3 years ago

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

        tmp = {}
        for key, v in dic.items():
            tmp.setdefault(v, []).append(key)

        res = []
        for i in range(k):
            res += tmp.pop(max(tmp))
            if len(res) == k:
                return res
JiangyanLiNEU commented 3 years ago

Idea

heyqz commented 3 years ago

代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        buckets = [[] for _ in range(len(nums) + 1)]
        d = {}
        for num in nums:
            d[num] = d.get(num, 0) + 1

        for num, freq in d.items():
            buckets[freq].append(num)

        res = []
        for i in range(len(buckets)-1, -1, -1): 
            bucket = buckets[i]
            if bucket:
                for num in bucket:
                    res.append(num)
        return res[:k]
xj-yan commented 3 years ago

Quick Select

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

        int[] array = new int[counterMap.size()];
        int index = 0;
        for (int n : counterMap.keySet()){
            array[index++] = n;
        }

        quickSelect(array, 0, array.length - 1, counterMap, k);
        return Arrays.copyOfRange(array, array.length - k, array.length);
    }

    private void quickSelect(int[] array, int left, int right, Map<Integer, Integer> map, int k){
        int pivot = map.get(array[right]), index = left;

        for (int i = left; i < right; i++){
            if (map.get(array[i]) <= pivot){
                swap(array, i, index++);
            }
        }
        swap(array, index, right);
        int count = right - index + 1;
        if (count == k) return;
        else if (count > k) quickSelect(array, index + 1, right, map, k);
        else quickSelect(array, left, index - 1, map, k - count);
    }

    private void swap(int[] nums, int i, int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

Time Complexity: Best Case: O(N), Worst Case: O(N^2) Space Complexity: O(N)

pophy commented 3 years ago

思路

Java code

    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> countMap = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            countMap.put(nums[i], countMap.getOrDefault(nums[i], 0) + 1);
        }
        PriorityQueue<Map.Entry<Integer, Integer>> priorityQueue = new PriorityQueue<>(Comparator.comparingInt(Map.Entry::getValue));
        for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
            priorityQueue.add(entry);
            if (priorityQueue.size() > k) {
                priorityQueue.poll();
            }
        }
        List<Integer> resList = new ArrayList<>();
        while (!priorityQueue.isEmpty()) {
            resList.add(priorityQueue.poll().getKey());
        }
        int[] res = new int[resList.size()];
        for (int i = 0; i < res.length; i++) {
            res[i] = resList.get(i);
        }
        return res;
    }

时间&空间

falconruo commented 3 years ago

思路:

  1. 使用hashmap存放数组的值和frequency
  2. 由大到小按照frequency排序:
    • 方法一:传统sort排序
    • 方法二:小顶堆(Min Heap),存放最多k个pair

复杂度分析: 方法一、 时间复杂度: O(nlogn), n为数组nums的元素个数 空间复杂度: O(n + k)

方法二 时间复杂度: O(nlogk), n为数组nums的元素个数 空间复杂度: O(n + k)

代码(C++):


//方法二:
class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        map<int, int> freq;

        // use a hashmap to store the frequency of each element
        for (auto n : nums) // O(n)
           freq[n]++;

        // use min heap to store the k most frequent elements

        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;

        for (auto f : freq) { // o(nlogk)
            if (pq.size() < k)
                pq.push({f.second, f.first}); // stack sort o(logk)
            else if (pq.top().first < f.second) {
                pq.pop();
                pq.push({f.second, f.first});
            }
        }

        vector<int> res;

        while (!pq.empty()) { // O(k)
            res.push_back(pq.top().second);
            pq.pop();
        }

        return res;
    }
};
MonkofEast commented 3 years ago

347. Top K Frequent Elements

Click Me

Algo

  1. hashmap, key->number, val->frequency
  2. Heap sort
  3. heap to arr

Code

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        # corner case
        if k == len(nums): return nums
        # collections.Counter is a hashmap that key->number, val->frequence
        count = collections.Counter(nums)
        # heapq.nlargest(k, count.keys(), key=count.get)
        # means "find k largest" + "from count.keys()" + "by count.get(akey)"
        return heapq.nlargest(k, count.keys(), key=count.get)

Comp

k is the number of n-largest

T: O(Nlogk)

S: O(N+k)

chakochako commented 3 years ago
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
    count = collections.Counter(nums)
    return [item[0] for item in count.most_common(k)]
yingliucreates commented 3 years ago

link:

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

代码 Javascript

const topKFrequent = (nums, k) => {
  const map = {};
  const result = [];
  const bucket = Array(nums.length + 1)
    .fill()
    .map(() => []);

  for (let num of nums) {
    map[num] = ~~map[num] + 1;
  }

  for (let num in map) {
    bucket[map[num]].push(parseInt(num));
  }

  for (let i = nums.length; i >= 0 && k > 0; k--) {
    while (bucket[i].length === 0) i--;
    result.push(bucket[i].shift());
  }

  return result;
};

复杂度分析

空间时间均为O(n)

pan-qin commented 3 years ago

idea: use a hashmap to record the frequency of each number. Then construct a min-Heap with size of k. The min-heap hold the entryset of the map. When it's size is larger than k, poll the top of the heap. In the end, output the whole heap. Time: O(NlogK) Space: O(n)

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

题目

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

思路

HashMap记录数字的频率,使用一个size为K的最小堆来记录,堆顶元素为前k个高频中频率最低的那个,当新的数字来时只需要对比两个的频率即可。

代码

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(Integer 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;
    }
}

复杂度分析

时间复杂度

O(n) + O (nlogk)

空间复杂度

O(n + k)

mmboxmm commented 3 years ago

思路

重点题,bucket 和 quickSelect都要练习一下

代码

fun topKFrequent(nums: IntArray, k: Int): IntArray {
  val map = nums.asSequence().groupingBy { it }.eachCount()
  val bucket = Array<MutableList<Int>?>(nums.size + 1) { null }

  map.forEach {
    bucket[it.value] = bucket[it.value]?.apply {
      add(it.key)
    } ?: mutableListOf(it.key)
  }

  val res = mutableListOf<Int>()
  for (freq in bucket.lastIndex downTo 1) {
    bucket[freq]?.apply {
      res.addAll(take(minOf(k - res.size, size)))
    }
    if (res.size == k) return res.toIntArray()
  }
  return res.toIntArray()
}

复杂度

zol013 commented 3 years ago

思路: 用hashmap记录数字的频率,然后将hashmap里的元素排序,然后返回前k个。 Python 3 Code:

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        hashmap = defaultdict(int)
        for num in nums:
            hashmap[num] += 1
        ans = []
        freqs = sorted(hashmap.items(), key = lambda x:x[1])
        while k > 0:
            num, freq = freqs.pop()
            ans.append(num)
            k -= 1
        return ans

Time Complexity: O(N*log(N) Space Complexity: O(N)

qixuan-code commented 3 years ago

LC 347. Top K Frequent Elements

Ideas

comment Runtime: 40 ms beat 75%

python代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:

        hashmap = dict()

        for num in nums:
            hashmap[num] = 0

        for num in nums:
            if num in hashmap:
                hashmap[num] +=1

        sort_map = dict(sorted(hashmap.items(), key = lambda item:item[1],reverse=True))
        i = 0
        result = []
        for num, count in enumerate(sort_map):
            if i < k:
                result.append(count)
                i = i+1
            else:
                break

        return result

复杂度分析

bingyingchu commented 3 years ago

import heapq

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        freq = {}

        for num in nums:
            freq[num] = freq.get(num,0) + 1

        heap = []
        for num, count in freq.items():
            heapq.heappush(heap,(count,num))
            if len(heap) > k:
                heapq.heappop(heap)

        return [pairs[1] for pairs in heap ]

# Time: O(nlogk) / Space: O(n + k)
wangzehan123 commented 3 years ago

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;
    }
}

复杂度分析

令 n 为数组长度。

ghost commented 3 years ago

题目

  1. Top K Frequent Elements

思路

Hash table and bucket sort

代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        memo = collections.defaultdict(lambda:0)
        bucket = [[] for _ in range(len(nums)+1)] 
        res = []

        for num in nums:
            memo[num] += 1        

        for key in memo:
            bucket[memo[key]].append(key)

        for i in range(len(bucket)-1, 0, -1):

            if k <=0: break
            if bucket[i]:
                res+=bucket[i]
                k -= len(bucket[i])

        return res

复杂度

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

Daniel-Zheng commented 3 years ago

思路

HashMap。

代码(C++)

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> hashMap;
        vector<pair<int, int>> count;
        vector<int> res;
        for (int i = 0; i < nums.size(); i++) {
            if (hashMap.count(nums[i])) {
                hashMap[nums[i]]++;
            } else {
                hashMap[nums[i]] = 1;
            }
        }
        for (auto &i : hashMap) count.push_back({i.second, i.first});
        sort(count.rbegin(), count.rend());
        for (int i = 0; i < k; i++) res.push_back(count[i].second);
        return res;
    }
};

复杂度分析

laofuWF commented 3 years ago
# use hashmap: key(num), value(-count)
# use priority queue to get top K frequent number
# time: O(NlogN), N is the number of unique elements in nums
# space: O(N)

import heapq

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        if not nums or not k:
            return []

        counter = {}
        for n in nums:
            counter[n] = counter.get(n, 0) - 1

        heap = []
        # push a pair into heap, sort by first element by default
        for key in counter:
            heapq.heappush(heap, (counter[key], key))

        res = []
        while k > 0 and heap:
            res.append(heapq.heappop(heap)[1])
            k -= 1

        return res
Menglin-l commented 3 years ago

思路:

小顶堆


代码部分:

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        // 先用map记住每一个元素出现的次数
        Map<Integer, Integer> count = new HashMap<>();
        for (int num : nums) {
            count.put(num, count.getOrDefault(num, 0) + 1);
        }

        // 自定义比较器,按出现次数升序排列
        PriorityQueue<Integer> pq = new PriorityQueue<>(k + 1, (a, b)->count.get(a) - count.get(b));

        // 填充队列
        for(int num : count.keySet()) {
            pq.add(num);
            if (pq.size() > k) pq.remove();
        }

        // 转换为数组并返回
        int[] ans = new int[k];
        int index = 0;
        while (!pq.isEmpty()) {
            ans[index ++] = pq.remove();
        }

        return ans;
    }
}

复杂度:

Time: O(Nlogk)

Space: O(N)

weichuliao commented 3 years ago

Main Idea

Code with Python

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        if k == len(nums):
            return nums

        count = collections.Counter(nums)

        return heapq.nlargest(k, count.keys(), key=count.get)

Complexity Analysis

SunStrongChina commented 3 years ago

347. 前 K 个高频元素

入选理由

暂无

题目地址

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

前置知识

  • 哈希表
  • 堆排序
  • 快速选择

题目描述

给定一个非空的整数数组,返回其中出现频率前  k  高的元素。
示例 1:

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

示例 2:

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

提示:

- 你可以假设给定的  k  总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
- 你的算法的时间复杂度必须优于 O(n log n) , n  是数组的大小。
- 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
- 你可以按任意顺序返回答案。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/top-k-frequent-elements
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:使用字典记录元素的出现频率,然后按照频率排序,取前几个就行了

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

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

pzl233 commented 3 years ago

思路

用HashMap存频率,用PriorityQueue取出频率最高的k个元素

代码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i : nums) {
            map.put(i, map.containsKey(i) ? map.get(i) + 1 : 1);
        }
        int[] result = new int[k];
        PriorityQueue<Integer> pq = new PriorityQueue<>( (a, b) -> map.get(b) - map.get(a));
        for (int i : map.keySet()) {
            pq.add(i);
        }
        for (int i = 0; i < k; i++) {
            result[i] = pq.poll();
        }
        return result;
    }
}

复杂度分析

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

shawncvv commented 3 years ago

思路

官方解题思路

代码

JavaScript Code

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function (nums, k) {
  const counts = {};
  for (let num of nums) {
    counts[num] = (counts[num] || 0) + 1;
  }
  let pairs = Object.keys(counts).map((key) => [counts[key], key]);

  select(0, pairs.length - 1, k);
  return pairs.slice(0, k).map((item) => item[1]);

  // 快速选择
  function select(left, right, offset) {
    if (left >= right) {
      return;
    }
    const pivotIndex = partition(left, right);
    console.log({ pairs, pivotIndex });
    if (pivotIndex === offset) {
      return;
    }

    if (pivotIndex <= offset) {
      select(pivotIndex + 1, right, offset);
    } else {
      select(left, pivotIndex - 1);
    }
  }

  // 拆分数组为两个part
  function partition(left, right) {
    const [pivot] = pairs[right];
    let cur = left;
    let leftPartIndex = left;
    while (cur < right) {
      if (pairs[cur][0] > pivot) {
        swap(leftPartIndex++, cur);
      }
      cur++;
    }
    swap(right, leftPartIndex);
    return leftPartIndex;
  }

  function swap(x, y) {
    const term = pairs[x];
    pairs[x] = pairs[y];
    pairs[y] = term;
  }
};

复杂度

xiaowenhe commented 3 years ago
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        counter = collections.Counter(nums)
        sorted_nums = sorted(counter.items(), key = lambda x: -x[1])
        result = [key for key, val in sorted_nums]
        return result[:k]
Francis-xsc commented 3 years ago

思路

哈希表+自定义排序

代码


class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int,int>m;
        for(auto x:nums)
            m[x]++;
        vector<pair<int,int>>v;
        for(pair<int,int> x:m)
            v.push_back(x);
        sort(v.begin(),v.end(),cmp);
        vector<int>res;
        for(int i=0;i<k;i++)
            res.push_back(v[i].first);
        return res;
    }
    static bool cmp(pair<int,int>a,pair<int,int>b)
    {
        return a.second>b.second;
    }
}; 

复杂度分析

liuyangqiQAQ commented 3 years ago

直接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);
        }
        return new ArrayList<>(map.keySet()).stream().sorted((o1, o2) -> map.get(o2) - map.get(o1)).limit(k).mapToInt(Integer::intValue).toArray();
    }
}
flame0409 commented 3 years ago
class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
        // 使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
        HashMap<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);
             }
        }
        // 遍历map,用最小堆保存频率最大的k个元素
        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()) {
            if (pq.size() < k) {
                pq.add(key);
            } else if (map.get(key) > map.get(pq.peek())) {
                pq.remove();
                pq.add(key);
            }
        }
        // 取出最小堆中的元素
        List<Integer> res = new ArrayList<>();
        while (!pq.isEmpty()) {
            res.add(pq.remove());
        }
        return res;
    }
}

时间复杂度:O(nlogn)

空间复杂度:O(n)

comst007 commented 3 years ago

347. 前K个高频元素


思路

先统计出每个元素的出现次数。
借助桶排序的思想从后往前遍历找出出现次数大于K的元素的最小出现频率。那原数组中
出现频率大于该最小频率的元素就是出现频率最高的K个元素。

代码

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> h_cnt;
        for(auto& cur:nums){
            h_cnt[cur]++;
        }
        vector<int> cnt_arr(nums.size() + 1, 0);
        for(auto [cur, cnt]: h_cnt){
            cnt_arr[cnt] ++;
        }

        int ans_res = 0;
        int target_cnt, ii;
        for(target_cnt = nums.size(); target_cnt >=0; -- target_cnt){
            ans_res += cnt_arr[target_cnt];
            if(ans_res >= k){
                break;
            }
        }
        vector<int> ans;
        for(auto [cur, cnt]: h_cnt){
            if(cnt >= target_cnt){
                ans.push_back(cur);
                if(ans.size() == k) break;
            }
        }
        return ans;
    }
};

复杂度分析

n 为数组元素个数。

jaysonss commented 3 years ago

思路

建立哈希表,保存下每个数字出现的次数

对哈希值列表进行排序

关键点˜

代码

Java Code:

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,int[]> map = new HashMap<>();
        for(int num : nums){
            int[] count = map.get(num);
            if(count == null){
                map.put(num,new int[]{num,1});
            }else{
                count[1]+=1;
            }
        }

        List<int[]> countList = new ArrayList<>(map.values());
        Collections.sort(countList,new Comparator<int[]>(){
            @Override
            public int compare(int[] o1, int[] o2) {
                return o2[1]-o1[1];
            }
        });
        int[] ans = new int[k];

        for(int i=0;i<k;i++){
            ans[i]=countList.get(i)[0];
        }
        return ans;
    }
}

复杂度分析

septasset commented 3 years ago

思考

关键点

代码(Python)

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        c = Counter(nums)
        # freqs = c.items()
        # sorted(freqs, key=lambda x:-x[1])
        return [x[0] for x in c.most_common(k)]

复杂度分析

hwpanda commented 3 years ago
const topKFrequent = (nums, k) => {
  let map = new Map()
  for (let i = 0; i < nums.length; i++) {
      if (map.has(nums[i])) {
          map.set(nums[i], map.get(nums[i]) + 1)
      }
      else {
          map.set(nums[i], 1)
      }
  }
  let res = [...map]
  res.sort((a, b) => b[1] - a[1])
  return res.map((n) => n[0]).slice(0, k)
};
Serena9 commented 3 years ago

代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        def sift_down(arr, root, k):
            val = arr[root] 
            while root<<1 < k:
                child = root << 1
                if child|1 < k and arr[child|1][1] < arr[child][1]:
                    child |= 1
                if arr[child][1] < val[1]:
                    arr[root] = arr[child]
                    root = child
                else:
                    break
            arr[root] = val

        def sift_up(arr, child):
            val = arr[child]
            while child>>1 > 0 and val[1] < arr[child>>1][1]:
                arr[child] = arr[child>>1]
                child >>= 1
            arr[child] = val

        stat = collections.Counter(nums)
        stat = list(stat.items())
        heap = [(0,0)]

        for i in range(k):
            heap.append(stat[i])
            sift_up(heap, len(heap)-1) 

        for i in range(k, len(stat)):
            if stat[i][1] > heap[1][1]:
                heap[1] = stat[i]
                sift_down(heap, 1, k+1) 
        return [item[0] for item in heap[1:]]