标签:
有一个整数数组,请你根据快速排序的思路,找出数组中第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