c++ 中 std::sort()使用了快速排序的算法,下面看下它的实现算法
快速排序的基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的数字均比另一部分数字小,则可分别对这两部分进行排序,以达到整个序列有序。
算法描述:https://www.bilibili.com/video/BV1at411T75o?from=search&seid=3870102746514763528
1.选定Pivot中心轴(随机选取,一般选数组第一个值为Pivot)
2.从后向前遍历,将大于Pivot中心轴的数字放在Pivot的右边
3.从前向后遍历,将小于Pivot中心轴的数字放在Pivot的左边
4.分别对左右子序列重复前三步
void quick_sort(vector<int> &nums, int l, int r){ //l=0,r=nums.size()
if(l+1 >= r) return;
int first=l, last=r-1, key=nums[first];
while (first < last){ //循环完会把nums分成两部分,左边小于k,右边大于k
while(first < last && nums[last] >= key){ //数组从后向前查找小于key的值,交换至左边
--last;
}
nums[first] = nums[last];
while(first < last && nums[first] <= key){ //数组从前向后查找大于key的值,交换至右边
++first;
}
nums[last]=nums[first];
}
nums[first] = key; //此时的first已不是0
quick_sort(nums, l, first);
quick_sort(nums, first+1, r);
}
215.数组中第k大元素
K-th Element描述:在一个未排序的数组中,找到第k大的数字。
输入输出:输入一个数组和一个目标值k,输出第k大的数字。题目默认一定有解。
题解:快速选择一般用于求解k-th Element问题,可以在O(n)时间复杂度,O(1)空间复杂度完成求解工作。快速选择的实现和快速排序相似,不过只需要
找到第k大的枢(pivot)即可,不需要对其左右边再进行排序,只需在范围内选择一边递归即可。与快速排序一样,快速选择一般需要先打乱数组,否则最坏
情况下时间复杂度为O(n^2),我们这里为了方便省略掉了打乱的步骤。
//主函数
int findKthLargest(vector<int>& nums, int k) {
int l=0, r=nums.size(), 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]; //l=r
}
//辅函数-快速选择
int quickSelection(vector<int>& nums, int l, int r) {
int first=l,last=r-1,key=nums[first];
while(first < last){
while(first<last && key <= nums[last]){
--last;
}
nums[first]=nums[last];
while(first<last && key >= nums[first]){
++first;
}
nums[last]=nums[first];
}
nums[first]=key;
return first;
}
347.前k个高频元素 桶排序
给定一个数组,求前k个最频繁的数字。
input:nums=[1,1,1,2,2,3,4], k=2
output:[1,2]
题解:顾名思义,桶排序的意思是为每个值设立一个桶,桶内记录这个值出现的次数(或其他属性),然后对桶进行排序。针对样例来说,我们先通过桶排序得到
四个桶[1,2,3,4],它们的值分别为[4,2,1,1],表示每个数字出现的次数。
紧接着我们对桶的频次进行排序,前k大桶即是前k个频繁的数。
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]); //map统计频次,找出最大的频次
}
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.szie() < k; --i){
for (const int & num:buckets[i]){
ans.push_back(num);
if(ans.size() == k){
break;
}
}
}
return ans;
}
类型:
- 贪心算法
- 双指针
- 二分查找
- 排序算法
- 二维数组的搜索
- 动态规划
- 数据结构-stl
- 字符串比较、匹配
- 链表
- 二叉树