zoukankan      html  css  js  c++  java
  • 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;
        }
    };
  • 相关阅读:
    动态传参
    函数的介绍
    文件的操作
    send email with formatted table
    minimize and close window with customed winform
    python algorithm
    something important about docker
    book list
    which language is suitable for what to do
    Find Duplicate Items in list fast
  • 原文地址:https://www.cnblogs.com/Bella2017/p/10421960.html
Copyright © 2011-2022 走看看