leetcode347 前K个高频元素

暴力的做法,先遍历一遍数组,然后把出现的数字与对应的出现次数放置在一个map中,而map自己无法根据value来排序,所以将map中的数据放置进一个vector中进行排序,撰写了一个函数用于排序的判定,最后输出前K个元素即可。贴代码

 1 typedef pair<int,int> PAIR;
 2 bool cmp_val(const PAIR &left,const PAIR &right)
 3 {
 4     return left.second > right.second;
 5 }
 6 class Solution {
 7 public:
 8     vector<int> topKFrequent(vector<int>& nums, int k) 
 9     {
10         map<int,int> res_temp;
11         vector<int> res;
12         for(auto temp:nums)
13         {
14             if(!res_temp.count(temp))
15             {
16                 res_temp.insert(pair<int,int>(temp,1));
17             }            
18             else
19             {
20                 (res_temp.find(temp)->second)++;
21             }
22         }
23         vector<PAIR> vec(res_temp.begin(),res_temp.end());
24         sort(vec.begin(),vec.end(),cmp_val);
25         vector<PAIR>::iterator it_temp = vec.begin();
26         for(int i = 0 ; i < k ; i++)
27         {
28             res.push_back(it_temp->first);
29             it_temp++;
30         }
31         return res;
32     }
33 };

接触到了一种新的数据结构,堆,本质上是二叉树,其特殊性质是父节点一定小于或者大于其两个子节点,分别为小顶堆与大顶堆。可以在C++中通过priority_queue这一数据结构实现。还是先通过map实现遍历,然后建立一个K大小的小顶堆,如果堆的元素个数小于 k,就可以直接插入堆中。如果堆的元素个数等于 kk,则检查堆顶与当前出现次数的大小。如果堆顶更大,说明至少有 kk 个数字的出现次数比当前值大,故舍弃当前值;否则,就弹出堆顶,并将当前值插入堆中。最后输出堆中所有元素的first值,贴代码。

 1 class Solution {
 2 public:
 3     static bool cmp(pair<int, int>& m, pair<int, int>& n) {
 4         return m.second > n.second;
 5     }
 6     vector<int> topKFrequent(vector<int>& nums, int k) 
 7     {
 8         map<int,int> res_temp;
 9         vector<int> res;
10         for(auto temp:nums)
11         {
12             if(!res_temp.count(temp))
13             {
14                 res_temp.insert(pair<int,int>(temp,1));
15             }            
16             else
17             {
18                 (res_temp.find(temp)->second)++;
19             }
20         }
21         priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> q(cmp);
22         for(auto& [num,count] : res_temp)
23         {
24             if(q.size() == k)
25             {
26                 if(q.top().second<count)
27                 {
28                     q.pop();
29                     q.emplace(num,count);
30                 }
31             }
32             else
33             {
34                 q.emplace(num,count);
35             }
36         }
37         while(!q.empty())
38         {
39             res.push_back(q.top().first);
40             q.pop();
41         }
42         return res;
43     }
44 };

还有一种方法,利用了快速排序的方法,快速排序的原理就是随机选定一个界限值,将大于该值的放在该值的左或者右,从而进行递归,而该例中不需要完成所有的排序,只需要得出k个最大的即可。如第一次排序出n个较大值,若n比k大,则继续进行排序,选择出k个最大的,若n比k小,先将n个值存储,然后在剩余值中选取k-n个较大值,同样能够完成,贴代码。

 1 class Solution {
 2 public:
 3     void quicksort(vector<pair<int,int>>& v,int start,int end, vector<int>& ret,int k)
 4     {
 5         int picked = rand()%(end - start +1)  + start;
 6         swap(v[start],v[picked]);
 7         int pivot = v[start].second;
 8         int index = start;
 9         for(int i = start+1 ; i <= end ; i++)
10         {
11             if(v[i].second>=pivot)          //将比pivot大的都放在index的左边
12             {
13                 swap(v[index+1],v[i]);
14                 index++;
15             }
16         }
17         swap(v[start],v[index]);
18         if(k<=index-start)
19         {
20             quicksort(v,start,index-1,ret,k);
21         }
22         else
23         {
24             for(int i = start ; i <= index ; i++)
25             {
26                 ret.push_back(v[i].first);
27             }
28             if(k>index-start+1)
29             {
30                 quicksort(v,index+1,end,ret,k-(index-start+1));
31             }
32         }
33     }
34     vector<int> topKFrequent(vector<int>& nums, int k) 
35     {
36         map<int,int> res_temp;
37         vector<int> res;
38         for(auto temp:nums)
39         {
40             if(!res_temp.count(temp))
41             {
42                 res_temp.insert(pair<int,int>(temp,1));
43             }            
44             else
45             {
46                 (res_temp.find(temp)->second)++;
47             }
48         }
49         vector<pair<int,int>> values;
50         for(auto &temp:res_temp)
51         {
52             values.push_back(temp);
53         }
54         quicksort(values,0,values.size()-1,res,k);
55         return res;
56     }
57 };

 另一种快速排序的写法,本质上还是类似的。

 1 class Solution {
 2 public:
 3     vector<int> topKFrequent(vector<int>& nums, int k) 
 4     {
 5         map<int,int> countMap;
 6         for(auto temp:nums)
 7         {
 8             if(!countMap.count(temp))
 9             {
10                 countMap.insert(pair<int,int>(temp,1));
11             }            
12             else
13             {
14                 (countMap.find(temp)->second)++;
15             }
16         }
17         vector<pair<int,int>> countVec;
18         for(auto &temp:countMap)
19         countVec.push_back(temp);
20         vector<int> resVec;
21         quicksort(countVec,0,countVec.size()-1,k,resVec);
22         return resVec;
23     }
24     void quicksort(vector<pair<int,int>>& countVec,int start,int end,int k,vector<int>& resVec)
25     {
26         int picked = rand()%(end - start +1)  + start;
27         swap(countVec[start],countVec[picked]);
28         int pivot = countVec[start].second;
29         int index = start;
30         for(int i = start+1 ; i <= end ; i++)
31         {
32             if(countVec[i].second>pivot)
33             {
34                 swap(countVec[index+1],countVec[i]);
35                 index++;
36             }            
37         }
38         swap(countVec[start],countVec[index]);
39         if(index+1>k)
40         quicksort(countVec,start,index-1,k,resVec);
41         else if(index+1 == k)
42         {
43             for(int i = 0 ; i <= index ; i++)
44             resVec.push_back(countVec[i].first);
45         }
46         else
47         quicksort(countVec,index+1,end,k,resVec);
48     }
49 };

 

posted @ 2021-08-24 20:37  zhaohhhh  阅读(73)  评论(0)    收藏  举报