zoukankan      html  css  js  c++  java
  • [LeetCode]Top K Frequent Elements

    题目:Top K Frequent Elements

    Given a non-empty array of integers, return the k most frequent elements.

    For example,
    Given [1,1,1,2,2,3] and k = 2, return [1,2].

    Note: 

      • You may assume k is always valid, 1 ? k ? number of unique elements.
      • Your algorithm's time complexity must be better than O(n log n), where n is the array's size.

    题意:给定一个非空整数数组,返回频度最大的k个元素。

    要求复杂度要小于O(nlogn)

    思路:

    首先,需要求出每个数的频度,可以使用map,这样只用遍历数组一次,就求出每个数的频度。

    然后找到频度最大的k个元素,返回。

    如何找到频度最大的k个元素呢?

    最直接的思路就是对上面得到的频度排序,这样就能得到频度最大的k个元素,但是排序算法的复杂度可能会变成O(n^2)。

    因此,应该还有更好的方法。

    我的思路是使用优先队列,保证队列中元素数量最大只有k个,这样直接返回优先队列中的元素就可以了。

    而且,优先队列会自动根据一个值排序,我希望按照频度来排序。

    当优先队列中已有k个元素时,每次新的元素要和频度最小的元素比较,取频度较大的元素。这样优先队列顶端的必须是频度最小的元素,所以我去频度的负数来做比较。

    优先队列是使用堆来实现的,每次插入元素是一个调整堆的过程,时间复杂度是O(logn)。所以这样时间复杂度必然是小于O(nlogn)的。

    vector<int> topKFrequent(vector<int>& nums, int k){
        unordered_map<int, int>frequents;
        for (auto i : nums)    ++frequents[i];//求出每个数的频度
        priority_queue<pair<int, int>>largerK;//first是频度的负数,这样保证top得到的是频度最小的
        auto it = frequents.begin();
        while (it != frequents.end()){
            if (largerK.size() < k)largerK.push({ -(it->second), it->first });//添加前k个元素
            else if(it->second > -(largerK.top().first)){//替换频度最小的
                largerK.pop();
                largerK.push({ -(it->second), it->first });
            }
            ++it;
        }
        vector<int>result;
        while (!largerK.empty()){//将k个数赋给数组
            result.push_back(largerK.top().second);
            largerK.pop();
        }
        return result;
    }
  • 相关阅读:
    云路五年 未来正来
    免费公测:RDS只读实例
    【Open Search产品评测】-- 淘点点:基于OpenSearch,轻松实现一整套O2O类搜索解决方案
    阿里云启动“云合计划” 培育中国“微软”级企业
    【Open Search产品评测】- 来往,7天轻松定制属于自己的搜索引擎
    水塘抽样算法
    如何调度考生的座位
    如何去除有序数组的重复元素
    二分查找高效判定子序列
    如何k个一组反转链表
  • 原文地址:https://www.cnblogs.com/yeqluofwupheng/p/7401975.html
Copyright © 2011-2022 走看看