题目描述
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
快速排序
快速排序思路
快速排序是一种速度比较快而且并不占用额外的空间的排序方法。
快速排序执行一个升序排列的一个单独步骤:
- 选定一个标志值 fv。
- 利用双指针的方式,<fv的元素移动到fv左边,将> fv的元素移动到fv右边。
- 将标志值左边的元素和右边的元素分别执行该步骤。
由于本题是最大的第K个元素,因此本题应该实现的是降序排序,只需要将步骤2的执行逻辑颠倒一下,也就是说:>fv的元素移动到fv左边,将< fv的元素移动到fv右边。
快速排序版本的代码
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
srand(time(0));
qSort(nums, 0, nums.size()-1,k-1);
return nums[k-1];
}
void qSort(vector<int> &num,int start,int end){
if(start < end){
int mid = qSortStep(num,start,end);
qSort(num,start,mid-1);
qSort(num,mid+1,end);
}
}
int qSortStep(vector<int> &num,int start,int end){
int p = start; //左指针
int q = end; //右指针
int t = rand()%(end-start+1)+start;
swap(num[start],num[t]);
int fv = num[start];
while(p < q){
while(p<q && num[q] < fv){q--;}
if(p < q){
swap(num[p],num[q]);
p++;
}
while(p<q && num[p] > fv){p++;}
if(p < q){
swap(num[p],num[q]);
q--;
}
}
num[p] = fv;
return p;
}
void swap(int& a,int& b){
int temp = a;
a = b;
b = temp;
}
};
优化
本题只需要第K个元素的位置,而我们将所有的元素重新排序不免有些浪费。因此,只需要在K会出现的区间执行快速排序的步骤即可。可以将qSort()函数修改成下面的样子:
int findKthLargest(vector<int>& nums, int k) {
srand();
qSort(nums, 0, nums.size()-1,k-1);
return nums[k-1];
}
void qSort(vector<int> &num,int start,int end,int kLoc){
if(start < end){
int mid = qSortStep(num,start,end);
if(kLoc < mid){
qSort(num, start, mid-1,kLoc);
}
else if(kLoc > mid){
qSort(num, mid+1,end,kLoc);
}
}
}
参数kLoc与题目中所给的k存在下面的关系:k = kLoc+1; kLoc是数组对应第k个位置的下标。