这是一道面试的算法题,当然可以用很多排序算法来实现,这些都是比价常规的。但是这道题要求不能排序,并且时间复杂度不能超过O(n^2).这里我们借用快速排序的衍生算法来实现。关于快速排序的实现,可以参考《经典算法学习——快速排序》这篇博客。示例代码上传至:https://github.com/chenyufeng1991/Front-N。
每一次的快排,都需要找一个基准值,然后从数组的两边交替开始和基准值比较,右边比基准值小的数移到左边,左边比基准值大的数移到右边,移到最后,只剩下一个位置了a[i],然后把基准值填入到a[i]中。此时,在基准值右边的数都比支点大。如果此时基准值的下标为i, 那么这个基准值就是第(endIndex-i+1)大的数了。endIndex是最后一个数的下标。
我们的目标是要找第N大的数,如果endIndex-i+1 = n,表示这个数我们找到了,具体说明如下:
记th = endIndex - i + 1 (表示当前下标为i的数字排名第th位)。find(a,startIndex,endIndex,n)
(1)th = n,返回基准值;
(2)th > n,说明第n大的数在基准值右边,所以在右边继续找:find(a,i+1,endIndex,n);
(3)th < n,说明第n大的数在基准值左边,在左边找第(n-th)大的数即可;find(a,startIndex,i-1,n-th);
代码实现:
1 #include<iostream> 2 3 using namespace std; 4 5 int __partition(int arr[],int l,int r){ 6 int e=arr[l]; 7 int j=l;//arr[l+1...j]<e 8 for(int i=l+1;i<=r;i++){ 9 if(arr[i]<e){ 10 j++; 11 swap(arr[j],arr[i]); 12 } 13 } 14 swap(arr[j],arr[l]); 15 return j; 16 } 17 18 void __quickSort(int arr[],int l,int r ,int m){ 19 if(l>r) 20 return; 21 int p=__partition(arr,l,r); 22 if(arr[p]>arr[m]) 23 __quickSort(arr,l,p-1,m); 24 else if(arr[p]<arr[m]) 25 __quickSort(arr,p+1,r,m); 26 else{ 27 cout<<arr[p]<<endl; 28 return; 29 } 30 31 32 } 33 34 void quickSort(int arr[],int n,int m){ 35 36 __quickSort(arr,0,n-1,m); 37 38 } 39 40 int main(){ 41 42 int m; 43 cin>>m; 44 45 int arr[10]={3,21,36,95,85,24,15,62,34,33}; 46 47 quickSort(arr,10,m); 48 49 for(int i=0;i<10;i++) 50 cout<<arr[i]<<" "; 51 cout<<endl; 52 53 return 0; 54 55 }