Problem describe:
在未排序的数组中找到第 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 ≤ 数组的长度。
解法
我们可以应用快速排序解决此问题
快速排序:
在快速排序中,每次排序过程中,我们需要选择一个主元素然后把数组分割为两部分:
1.大于等于主元素的元素
2.小于等于主元素的元素
首先,举个例子,数组[3,2,1,5,4,6],假设每次选最左边的元素作为主元素,那么我们在一次排序后,数组变为[5,6,4,3,1,2]。现在3变成了第四大的元素。
现在我们既然知道了3是第四大的元素,若我们要找第二大的元素,那么它一定在3的左边,如果我们向找到第五大的元素,那么它一定在3的右边,所以,平均来说,问题转变为原问题规模的一半,即T(n)=T(n/2)+O(n)
.现在我们只需要考虑数组的一半,所以问题可以在线性时间内解决
算法步骤如下:
1初始化左右下标,左下标为0,右下标为nums.size()-1;
2分割数组,如果主元素正好在k-1的下标处,返回它
3如果主元素在k-1下标的右边,则更新右下标为左数组的尾元素
4否则更新左下标为右数组的头元素
5重复步骤2
class Solution{
public:
int findkthLargest(vector<int>& nums,int k){
int left =0;
int right=nums.size()-1;
while(true)
{
int p=partition(nums,left,right);
if(p==k-1) return nums[p];
if(p>k-1) right=p-1;
else
left =p+1;
}
}
int partition(vector<int>& nums, int left, int right){
int pivot =nums[left],l=left+1,r=right;
while(l<=r)
{
if(nums[l]<pivot&&nums[r]>pivot)
swap(nums[l++],nums[r--]);
if(nums[l]>=pivot) l++;
if(nums[r]<=pivot) r--;
}
swap(nums[left],nums[r]);
return r;
}
}