题目链接:点击查看
题目描述:
在一个未排序的数组中,找到第 k 大的数字。
输入输出:
输入: [3,2,1,5,6,4]和k = 2 输出: 5
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4
题目分析:
快速选择一般用于求解
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()-1,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];
}
int quickSelection(vector<int>&nums,int l,int r)//此函数的算法思想来源于快速排序
{
int i=l+1,j=r; //i=l+1即将第一个数设置为基准数
while(true)
{
while(i<r&&nums[i]<=nums[l])
{
++i;
}
while(l<j&&nums[j]>=nums[l])
{
--j;
}
if(i>=j)
{
break;
}
swap(nums[i],nums[j]);
}
swap(nums[l],nums[j]);//基准数归位
return j;//与快速排序不同的是:此函数仅为快速排序的一层遍历 ,每一次调用即完成一层 (传递的为引用故直接对原生的nums进行操作)
//因为本题的目的不是排序而是 找出第k大的数 达到目的即可
}
快速排序代码:
void quick_sort(vector<int> &nums, int l, int r) //基于二分法的快排
{
if (l + 1 >= r)
{
return;
}
int first = l, last = r - 1, key = nums[first];
while (first < last)
{
while(first < last && nums[last] >= key)
{
--last;
}
nums[first] = nums[last];
while (first < last && nums[first] <= key)
{
++first;
}
nums[last] = nums[first];
}
nums[first] = key;
quick_sort(nums, l, first);
quick_sort(nums, first + 1, r);
}