内容会持续更新,有错误的地方欢迎指正,谢谢!
题目
有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数。
给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在。
输入例子:[1,3,5,2,2],5,3
输出例子:2
分析
比这套卷子前面两道题简单多了!送分题,知道快排的都知道Partition这个用于分区的函数,那么利用Partition函数就解决了。
思想就是快速排序的划分,步骤如下:
- 进行一次快排,假设得到的中轴为mid,大的放mid前面,小的放mid后面
- 判断 mid - low + 1 == K ,如果成立,直接输出a[mid]
- 如果 mid - low + 1 > K, 则第K大的元素在前半段,此时更新right = mid - 1,继续进行步骤1
- 如果mid - low + 1 < K, 则第K大的元素在后半段, 此时更新left = mid + 1, 且 K = K - (mid - low + 1),继续步骤1
由于常规快排要得到整体有序的数组,而此方法每次可以去掉“一半”的元素,从而变成了线性查找,故实际的复杂度不是O(nlgn),而是O(n)。
所用数据结构: vector
代码
class Finder
{
public:
int Partition(vector<int>& a,int left,int right)//正常的Partition()
{
int p=a[left];
while(left<right)
{
while(left<right&&a[right]<=p)
--right;
a[left]=a[right];
while(left<right&&a[left]>=p)
++left;
a[right]=a[left];
}
a[left]=p;
return left;
}
int findKth(vector<int>& a, int K, int low, int high)//多态
{
int p=Partition(a,low,high);
if(p-low+1==K)
return a[p];
else if(p-low+1>K)
return findKth(a,K,low,p-1);//注意加return
else
return findKth(a,K-(p+1)+low,p+1,high);//注意加return
}
int findKth(vector<int> a, int n, int K)
{
return findKth(a,K,0,n-1);
}
};