解决思路:
将1亿个数字的前10000个(0~9999)进行排序(由大到小),获得res[]
,minIdx = zoneBeginIdx= 9999
(zoneBeginIdx:可能发生替换的区域的最前面的一个) ;
后面(10000 ~ 1亿-1)遍历,每次都与res
最后一个(即最小的作比较),
如果比res[minIdx]大,则res[minIdx] = res[当前]
,替换完后我们要保证最小的数字在 可能发生替换的区域 内,但此时该数字可能比res[9998]甚至res[0…9997]大,所以我们要判断是否让zoneBeginIdx
往前扩一个:--zoneBeginIdx
。
可以发现:只要我们能确认区域界线右边的第一个数字 与 区域边界左边的第一个数字大小关系 即可,最方便的方法就是当插入的数字在区域边界右边第一个位置时,扩展区域,这样两边的关系一定可以确认,扩展完后再找到最小的数字idx,便于下次替换;
继续往后遍历。
template< class T, class I >
void solution_4( T BigArr[], T ResArr[] )
{
//取最前面的一万个
memcpy( ResArr, BigArr, sizeof(T) * RES_ARR_SIZE );
//排序
std::sort( ResArr, ResArr + RES_ARR_SIZE, std::greater_equal() );
//最小元素索引
unsigned int MinElemIdx = RES_ARR_SIZE - 1;
//可能产生交换的区域的最小索引
unsigned int ZoneBeginIdx = MinElemIdx;
//遍历后续的元素
for( unsigned int i = RES_ARR_SIZE; i < BIG_ARR_SIZE; ++i )
{
//这个后续元素比ResArr中最小的元素大,则替换。
if( BigArr[i] > ResArr[MinElemIdx] )
{
// 1.替换最小的
ResArr[MinElemIdx] = BigArr[i];
// 2.重新定边界
// 交换的数字可能比区域边界前的数字还大,需要将边界左边最小的数字拿来一起比
if( MinElemIdx == ZoneBeginIdx )
--ZoneBeginIdx;
//3.查找定边界后的最小元素
unsigned int idx = ZoneBeginIdx;
unsigned int j = idx + 1;
for( ; j < RES_ARR_SIZE; ++j )
{
if( ResArr[idx] > ResArr[j] )
idx = j;
}
MinElemIdx = idx;
}
}
}
欢迎大家评论哟!如果本文对您有帮助,请点个赞,您的点赞对我很重要!这次一定!感谢!!!
转发请注明出处呦!感谢!!!