标签:
有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数。
给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在。
int quicksort(vector<int>&a,int i,int j)
{
int k=a[i];
while(i<j)
{
while(j>i&&a[j]>=k)j--;
if(i<j)
{
a[i]=a[j];
i++;
}
while(i<j&&a[i]<=k)i++;
if(i<j)
{
a[j]=a[i];
j--;
}
}
a[i]=k;
return i;
}
int findKth(vector<int> a, int n, int K) {
// write code here
int m=quicksort(a,0,n-1);
quicksort(a,0,m-1);
quicksort(a,m+1,n-1);
return a[n-K];
} 思路我觉得没问题,但总是得不到正确结果。而且例子给我的是49个数。没看出错误我就跟代码,第一步即刻发现我快排没排对啊。这样我就着重看快排。果然3个quicksort是什么鬼啊?应该是分治递归。这样代码改为如下即可。 int quicksort(vector<int>&a,int i,int j)
{
int k=a[i];
while(i<j)
{
while(j>i&&a[j]>=k)j--;
if(i<j)
{
a[i]=a[j];
i++;
}
while(i<j&&a[i]<=k)i++;
if(i<j)
{
a[j]=a[i];
j--;
}
}
a[i]=k;
return i;
}
void quickMerge(vector<int>&A,int l,int j)
{
if(l<j)
{
int m=quicksort(A,l,j);
quickMerge(A,l,m-1);
quickMerge(A,m+1,j);
}
}
int findKth(vector<int> a, int n, int K) {
// write code here
quickMerge(a,0,n-1);
return a[n-K];
} 这个复杂度当然是O(nlogn),但是在分治的基础上修改代码也可以采用如下方法。 int findKth(vector<int> a, int n, int K) {
return quickfind(a, 0, n-1, K);
}
int quickfind(vector<int>& a, int left, int right, int k) {
int i = left;
int j = right;
int mark = a[left];
while (i < j) {
while (i < j && a[j] >= mark)
--j;
if (i < j)
a[i++] = a[j];
while (i < j && a[i] <= mark)
++i;
if (i < j)
a[j--] = a[i];
}
a[i] = mark;
//哨兵右侧比他大的数字个数
int big_num = right - i;
//如果哨兵刚好是第K大的数
if (k - big_num - 1 == 0)
return mark;
else if (k - big_num - 1 > 0) {
//如果右侧数字个数不够K个,则从左侧找第k-big_num-1大的数
return quickfind(a, left, i - 1, k - big_num - 1);
} else {
//如果右侧数字个数比K多,则在右侧找第K大的数
return quickfind(a, i + 1, right, k);
}
}
这样的话复杂度肯定降低,因为只用递归调用一边,否则要完成排序需要调用两边。虽然浪费了很长时间,但找到了问题的关键我还是很开心的。标签:
原文地址:http://blog.csdn.net/yutianxin123/article/details/52088331