作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4046399.html
使用分治算法,首先选择随机选择轴值pivot,并使的序列中比pivot小的数在pivot左边,比pivot大的数在pivot右边,即快速排序算法中的partition的过程,可以参考:快速排序算法 Quick sort。
进行partition过程后,我们随机选择的轴值为序列的第j个,且其左边有a个数,右边有b个数。
如果j=k,那么说明该轴值就是第k小个数。
如果j>k,说明第k小的数一定在轴值的左边,我们可以递归的查找左侧a个数中的第k大个数。
如果j<k,说明第k小的数一定在轴值的右侧,且其左侧的a+1个数都小于第k小的数,所以我们可以递归的查找右侧b个数中的第k-a-1小的数。
由于每次规模缩小一半,且每次处理的时间为O(n),那么我们可以得到其平均复杂度为:T(n)=T(n/2)+n
根据主定理我们可以得到算法的复杂度为O(n)
代码如下:
1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #include <vector> 5 #include <ctime> 6 using namespace std; 7 void swap(int &a, int &b) 8 { 9 int tmp = a; 10 a = b; 11 b = tmp; 12 } 13 int partation(vector<int> &vec, int begin, int end, int pivot) 14 { 15 swap(vec[pivot], vec[begin]); 16 int tmp = vec[begin]; 17 int p = begin, q = end; 18 while( p < q ) 19 { 20 while( p < q && vec[q] >= tmp) q--; 21 if( p < q ) vec[p++] = vec[q]; 22 while( p < q && vec[p] < tmp ) p++; 23 if( p < q ) vec[q--] = vec[p]; 24 } 25 vec[p] = tmp; 26 return p; 27 } 28 int FindKMin(vector<int> & vec, int begin, int end, int k) 29 { 30 srand(time(0)); 31 int piovt = rand()%(end-begin+1)+begin; 32 int pos = partation(vec, begin, end, piovt); 33 if( pos-begin+1 == k ) 34 { 35 return vec[pos]; 36 } 37 else if( pos-begin+1 > k ) 38 { 39 return FindKMin(vec, begin, pos-1, k); 40 } 41 else 42 { 43 return FindKMin(vec, pos+1, end, k-(pos-begin+1)); 44 } 45 } 46 int main(int argc, char *argv[]) 47 { 48 int n; 49 vector<int> vec; 50 while( cin >> n ) 51 { 52 vec.clear(); 53 int k; 54 cin>>k; 55 int tmp; 56 for( int i = 0 ; i < n ; i++ ) 57 { 58 cin>>tmp; 59 vec.push_back(tmp); 60 } 61 cout<<FindKMin(vec, 0, vec.size()-1, k)<<endl; 62 } 63 }