• 347,23


    典型可以使用优先队列的。

    (小顶堆)

    class Solution {
    public:
        vector<int> topKFrequent(vector<int>& nums, int k) {
            
            assert(k>0);
            
            //统计每个元素出现的频率
            unordered_map<int,int> freq;   //freq<元素,频率>
            for(int i=0; i<nums.size();i++){
                freq[nums[i]] ++;  
            }
            
            assert(k<=freq.size());
            
            //扫描freq,维护当前出现频率最高的k个元素
            //在优先队列中,按照频率排序,所以数据对是(频率,元素)的形式.因为在pair中比较时,先比较的是频率
            priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>> > pq;  //优先队列,从小到大排序
            
            for(unordered_map<int, int>::iterator iter = freq.begin(); iter!=freq.end(); iter++){
                
                //当前的优先队列已经维护了k个出现频率最高的元素
                if(pq.size() == k){
                    if(iter->second > pq.top().first){ //iter<元素,频率>
                        pq.pop();   //将更小频率的元素扔掉
                        pq.push(make_pair(iter->second, iter->first));
                    }
                }
                else
                    pq.push(make_pair(iter->second, iter->first));
            }
            
            vector<int> res;
            while(!pq.empty()){
                res.push_back(pq.top().second);
                pq.pop();
            }
            return res;
        }
    };
    
    

     但是若k和n差不多大,方法二就比较耗时了。则方法三的优势就很明显了。

    typedef pair<int, int> PAIR; 
    class Solution {
    public:
        
        static int cmp(PAIR &a, PAIR &b){
            
            return a.second>b.second;
        }
        
        vector<int> topKFrequent(vector<int>& nums, int k) {
            
            vector<int> v;
            map<int, int> m;
            vector<PAIR> pair_vec;
            for(int i=0;i<nums.size();++i){
                
                m[nums[i]]++;
            }
            for(map<int,int>:: iterator it = m.begin(); it!=m.end(); ++it){
                
                pair_vec.push_back(make_pair(it->first, it->second));
            }
            sort(pair_vec.begin(), pair_vec.end(),cmp);
            vector<PAIR>::iterator it = pair_vec.begin();
            while(k--){
                
                v.push_back(it->first);
                ++it;
            }
            
            return v;
        }
        
    };

    合并前的k个链表是有序的,最终合并后的链表也是有序的

     使用优先队列(小顶堆),先将K个链表的首元素都加入最小堆中,然后每次取出最小的那个元素加入到最终的链表中。然后把取出元素的下一个元素再加入堆中,下次仍从堆中取出最小的元素做相同的操作。以此类推,直到堆中没有元素了。此时返回合成链表的首结点。

     这里注意两点:

    1)比较函数的写法;

    2)由于优先队列默认是大顶堆,它重载了< ,优先队列会认为 a < b ,即 b 的优先级比 a 高,所以 b会被先出队,假设 a->val > b->val 为 TRUE,这样就实现了关键字小的元素先出队。它和sort比较函数的写法是相反的。

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        
        struct cmp{
            bool operator()(ListNode* a, ListNode* b){
                return a->val > b->val;
            } 
        };
        
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            priority_queue<ListNode*, vector<ListNode*>,cmp> q;
            
            //将k个链表的首结点推入优先队列中
            for(int i=0;i<lists.size();i++)
                if(lists[i])
                    q.push(lists[i]);
            
            ListNode* dummy = new ListNode(-1), *cur = dummy, *t = NULL;
            while(!q.empty()){
                t = q.top();
                q.pop();
                cur->next = t;
                cur = cur->next;
                if(cur->next)
                    q.push(cur->next);
            }
            return dummy->next;
        }
    };
  • 相关阅读:
    玩玩微信公众号Java版之一:配置微信公众平台服务器信息
    Centos6.5网络配置
    Java调用XML的方法:DocumentBuilderFactory
    JDK动态代理的简单理解
    日志组件logback的介绍及配置使用方法
    Win7-64位PowerDesigner下MySQLODBC驱动问题
    为什么要使用SLF4J而不是Log4J
    plsql 不修改tnsnames.ora文件
    oracle创建表空间
    Linux系统下安装jdk1.8
  • 原文地址:https://www.cnblogs.com/Bella2017/p/10421960.html
Copyright © 2020-2023  润新知