文章目录
常见的排序算法
在C++中,可以通过std::sort()进行排序,熟悉排序算法主要锻炼自己编程能力,加深自己对算法的理解。
算法时间复杂度:
比较类排序
通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
多路归并排序
非比较类排序
不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
快速排序类型题
215.数组中的第K个最大元素
题目描述
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
输入输出样例
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
题解
快速选择一般用于求解 k-th Element 问题,可以在 O(n) 时间复杂度,O(1) 空间复杂度完成求解工作。快速选择的实现和快速排序相似,不过只需要找到第 k 大的枢(pivot)即可,不需要对其左右再进行排序。
代码
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int l = 0, r = nums.size() - 1, target = nums.size() - k;
while (l < r) {
int mid = quickSelection(nums, l, r);
if (mid == target) {
return nums[mid];
}
if (mid < target) {
l = mid + 1;
}
else {
r = mid - 1;
}
}
return nums[l];
}
// 辅函数 - 快速选择
int quickSelection(vector<int>& nums, int l, int r) {
int i = l + 1, j = r;
while (true) {
while (i < r && nums[i] <= nums[l]) {
++i;
}
while (l < j && nums[j] >= nums[l]) {
--j;
}
if (i >= j) {
break;
}
swap(nums[i], nums[j]);
}
swap(nums[l], nums[j]);
return j;
}
};
75.颜色分类(Medium)
题目描述
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
输入输出样例
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
题解
类似三路快排,进行划分
代码
class Solution {
public:
void sortColors(vector<int>& nums) {
int low=0,high=nums.size()-1;
if(low>=high) return;
int i=low,j=low;
int k=high;
while(i<=k){
if(nums[i]==0) swap(nums[i++],nums[j++]);
else if(nums[i]==2) swap(nums[i],nums[k--]);
else i++;
}
}
};
桶排序类型题
347.前K个高频元素
题目描述
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
输入输出样例
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
代码
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> counts;
int max_count = 0;
for (const int& num : nums) {
max_count = max(max_count, ++counts[num]);
}
vector<vector<int>> buckets(max_count + 1);
for (const auto& p : counts) {
buckets[p.second].push_back(p.first);
}
vector<int> ans;
for (int i = max_count; i >= 0 && ans.size() < k; --i) {
for (const int& num : buckets[i]) {
ans.push_back(num);
if (ans.size() == k) {
break;
}
}
}
return ans;
}
};
451.根据字符出现频率排序(Medium)
题目描述
给定一个字符串,请将字符串里的字符按照出现的频率降序排列。
输入输出样例
输入:
"tree"
输出:
"eert"
解释:
'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
代码
class Solution {
public:
string frequencySort(string s) {
unordered_map<char,int> mp;
int maxmp=0;
for(auto& ch:s){
maxmp=max(maxmp,++mp[ch]);
}
vector<string> buckets(maxmp+1);
for(auto &[ch,num]:mp){
buckets[num].push_back(ch);
}
string ret;
for(int i=maxmp;i>0;i--){
string &bucket=buckets[i];
for(auto &ch:bucket){
for(int k=0;k<i;k++){
ret.push_back(ch);
}
}
}
return ret;
}
};
本文排序算法主要参考一像素博客学习整理。