文章目录
第 5 章 千奇百怪的排序算法
5.1 常用排序算法
以下是一些最基本的排序算法。虽然在 C++ 里可以通过 std::sort() 快速排序,而且刷题时很少需要自己手写排序算法,但是熟习各种排序算法可以加深自己对算法的基本理解,以及解出由这些排序算法引申出来的题目。
5.2 快速选择
[215. 数组中的第K个最大元素]
题目描述
在一个未排序的数组中,找到第 k 大的数字。
输入输出样例
输入一个数组和一个目标值 k,输出第 k 大的数字。题目默认一定有解。
Input: [3,2,1,5,6,4] and k = 2
Output: 5
题解
将所有元素放入优先队列,优先队列的顶端就是当前最大的数
然后弹出k - 1次最大的顶端数字,最后剩下的顶端就是我们需要的答案
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int , vector<int> , less<int>> q;
for(int i = 0 ; i < nums.size() ; i++){
q.push(nums[i]);
}
for(int i = 0 ; i < k - 1; i++){
q.pop();
}
return q.top();
}
};
5.3 桶排序
[347. 前 K 个高频元素]
题目描述
给定一个数组,求前 k 个最频繁的数字。
输入输出样例
输入是一个数组和一个目标值 k。输出是一个长度为 k 的数组。
Input: nums = [1,1,1,1,2,2,3,4], k = 2
Output: [1,2]
在这个样例中,最频繁的两个数是 1 和 2。
题解
把元素出现的次数计数 first保存值 second保存出现次数
使用优先队列,把出现次数多的排在前面
小结
- 遍历容器的话,感觉还是新特性好用一些,以后都用新特性,别忘了用引用,返回的是值不是指针
- 使用vector来说虽然麻烦了一点,但是相对优先队列来说他可以用下标访问,更加方便,功能更多
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int , int> mm;
for(auto & num : nums) mm[num]++;
vector<pair<int , int>> vv;
for(auto & it : mm) vv.push_back(it);
sort(vv.begin() , vv.end() , [](pair<int , int> pa1 , pair<int , int> pa2){
return pa1.second > pa2.second;
});
vector<int> ans;
for(auto & a : vv){
ans.push_back(a.first);
if(ans.size() == k) return ans;
}
return ans;
}
};
- 使用优先队列,每次访问元素都要出队,有点麻烦
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int , int> mm;
for(int x : nums) mm[x]++;
priority_queue<pair<int , int>> pq;
for(auto& p : mm)pq.push({p.second , p.first});
vector<int> ans(k);
for(int i = 0 ; i < k ; i++){
ans[i] = pq.top().second;
pq.pop();
}
return ans;
}
};
5.4 练习
[451. 根据字符出现频率排序]
题目描述:
给定一个字符串
s
,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。返回 已排序的字符串 。如果有多个答案,返回其中任何一个。
示例 1:
输入: s = "tree"
输出: "eert"
解释: 'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
题解:
- 先用unordered_map计算出每个元素出现的频率
- 用vector保存元素及其他出现的频率,然后排序让频率高的放在前面
- 用string保存排好序的元素,返回字符串
class Solution {
public:
string frequencySort(string s) {
unordered_map<char , int> mm;
for(char & ch : s) mm[ch]++;
vector<pair<char , int>> v;
for(auto pa : mm) v.push_back(pa);
sort(v.begin() , v.end() , [](pair<char , int> p1 , pair<char , int> p2){
return p1.second > p2.second;
});
string ss = "";
for(auto pa : v){
for(int i = 0 ; i < pa.second ; i++){
ss.push_back(pa.first);
}
}
return ss;
}
};