int find_k( int p[], int n, int k )
{
//k数组
int kList[ k ];
//k数组的初始化
for( int i = 0; i < k; i++ )
kList[ i ] = 0;
for( int i = 0; i < n; i++ )
{
//比对k数组中的数
for( int j = 0; j < k; j++ )
{
if( p[ i ] > kList[ j ] )
{
//后移操作
for( int l = k - 1; l > j; l-- )
kList[ l ] = kList[ l - 1 ];
//取代
kList[ j ] = p[ i ];
break;
}//end if
}//end for j
}//end for i
return kList[ k -1 ];
}
int find_k( vector find, int k )
{
if( find.size() < k )
{
return 0;
}//end if
int p = find.at(0);
//Sa 和 Sb数组
vector findA, findB;
//不将轴值放入左右两边数组
for( int i = 1; i < find.size(); i++ )
{
if( find.at( i ) >= p )
findA.push_back( find.at( i ) );
else
findB.push_back( find.at( i ) );
}//end for
if( findA.size() == ( k - 1 ) )
{
return p;
}//end if
else if( findA.size() > (k - 1) )
{
return find_k( findA, k );
}//end if
else
{
//2015年9月28日看到 u012780602反馈发现这里存在问题
//修改后已经解决
return find_k( findB, k - findA.size() - 1 ) ;
}//end else
}
//end find_k
class minHeap{
private:
int* Heap; //用于存放堆元素的数组
int size; //数组大小
int n; //堆中元素个数
void shiftdown( int ); //堆的下拉操作
public:
minHeap( int* Heap, int num, int max )
bool isLeaf( int pos ) const
int leftchild( int pos ) const
int rightchild( int pos ) const
int parent ( int pos ) const
bool insert( const int );
bool removeMin( int& );
int getMin();
};
//end class minHeap
因为对于保存的k个数,其中最小的数就是其第k大的数,因此采用最小值堆,对于堆需要操作的时候,是检查到数列中的数大于这个最小值,那么堆就要进行更新,要删除当前的最小值,并加入新值(就是淘汰最后面那个数)。而对于堆的操作无论是插入,还是删除时间复杂度都是O(logK)的,K为堆的大小。因此修改之前的算法,那么,时间复杂度近一步降低到了O( N*logK ),至此我优化的过程结束。再往《编程之美》这一节往下看,正好与其思想不谋而合,书中指出,这样的解决,还可以解决当需要查找的数列不能完全读入内存的情况。还是那句话,think it deeper, code it simple.
2015年8月12日
最近在看排序的一些内容,对这个又有了新的想法。
上述文中提及,快速排序的算法可以用以找第K大的数,然而用以找第K大的数的排序算法不应只有快排。同样,最常见的冒泡排序以及它的改进算法选择排序都可以用以寻找第K大的数。
冒泡排序的第k趟,就是寻找到第k个最值,并将其放置对应位置,冒泡排序本身写起来很简单,所以这个也不会难到哪里去。
template
Elem findK( Elem *A, int n, int k )
{
for( int i = 0; i < k; i++ )
for( int j = n - 1; j > 0; j-- )
if( A[ j ] > A[ j -1 ] )
{
Elem temp = A[ j ];
A[ j ] = A[ j - 1 ];
A[ j - 1 ] = temp;
}
return A[ k -1 ];
}//end findK
template
Elem findK( Elem *A, int n, int k )
{
for( int i = 0; i < k; i++ )
{
int index = i;
for( int j = n - 1; j > 0; j-- )
if( A[ j ] > A[ index ] )//只是寻找
index = j;
//最后才下手
Elem temp = A[ index ];
A[ index ] = A[ i ];
A[ i ] = temp;
}//end for i
return A[ k -1 ];
}//end findK
新浪博客地址:
http://blog.sina.com.cn/u/1822488043