/* 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; }