快速排序的变种——快速选择算法
给出一个数组,例如[1,4,2,6,8,3],现在要求出第 k 大的数字,即将数组从大到小排列,选择第k个数。用什么算法更快找到这个数?
最容易想到的就是先将数组排序,就可以很容易找到第 k 大的数字。就算用快速排序,时间复杂度为 O(nlgn)。有没有更快的算法?
快速排序每次将数组分成两部分,升序排列时,左半部分元素都大于右半部分元素,假设某次划分结果如下,中间元素下标为 mid,如果 k==mid,表示 mid 就是最终结果。如果 k>mid,说明结果在右半部分中,如果 k<mid,说明结果在左半部分。这就表明,我们划分完之后,只需再接着处理其中一半就可以,快速排序需要处理左右两部分。基于这个思想,我们将其称为快速选择算法。
快速选择算法 时间复杂度 O(n) 空间复杂度 (O(lgn))
数组中的第K个最大元素
详细题解
我的 AC 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class Solution { public: int quickSelect(vector<int>& nums,int l,int r,int k){ int mid = partion(nums,l,r); if(mid==k) return nums[mid]; if(k<mid) return quickSelect(nums,l,mid-1,k); else return quickSelect(nums,mid+1,r,k); } int partion(vector<int>& nums,int l,int r){ random(nums,l,r); int key = nums[l]; while(l<r){ while(l<r && nums[r]<=key){ --r; } nums[l] = nums[r]; while(l<r && nums[l]>=key){ ++l; } nums[r] = nums[l]; } nums[l] = key; return l; } inline void random(vector<int>& nums,int l,int r){ int R = rand() % (r-l+1)+l; swap(nums[l],nums[R]); } int findKthLargest(vector<int>& nums, int k) { srand(time(0)); int len = nums.size(); return quickSelect(nums,0,len-1,k-1); } };
|
关于快速排序的详细分析:快速排序分析及优化