我一次给出一个非常大的数字列表,我需要打印" 中位数 ".
更清楚的是,可以有" 125,000,000 "数字,并保证每个数字小于" 1.e + 18 ".
这是一场比赛,因此有内存限制(20 MB顶部)和时间限制(5秒顶部).
" 中位数 "是排序数字中间的数字.
例如,如果这是数字列表:
23
8
16
42
15
4
108
Run Code Online (Sandbox Code Playgroud)
排序后的数字:
1) 4
2) 8
3) 15
4) 16
5) 23
6) 42
7) 108
Run Code Online (Sandbox Code Playgroud)
" 中位数 "将是16;
所以我在互联网上搜索它,但我找不到任何通过这些限制的答案.
我的方法是获取所有数字,将它们保存在文本文件中,对它们进行排序,然后得到" 中位数 ".
因此,我想要优化其中一个想法,以便通过限制或通过这些限制的任何新想法.
我更喜欢使用第二个想法,因为与其他两个不同,它通过限制,但我不能这样做,因为我不知道如何在文本文件的中间插入一行.因此,如果我了解这一点,其余的过程将非常简单.
这是一个接收数字的函数,通过读取文件,找到它的最佳位置并将其放在那里.
事实上,它代表了我的第三个想法.
所以它有效(我用很多输入测试了它)但是我之前提到的问题是时间限制.
void insertNewCombinedNumber ( int combinedNumber )
{
char combinedNumberCharacterArray[ 20 ];
bool isInserted = false;
ofstream combinedNumbersOutputFile;
ifstream combinedNumbersInputFile;
// Operate on First File
if ( isFirstCombinedFileActive )
{
combinedNumbersOutputFile.open ( "Combined Numbers - File 01.txt" );
combinedNumbersInputFile.open ( "Combined Numbers - File 02.txt" );
}
// Operate on Second File
else
{
combinedNumbersOutputFile.open ( "Combined Numbers - File 02.txt" );
combinedNumbersInputFile.open ( "Combined Numbers - File 01.txt" );
}
if ( !combinedNumbersInputFile )
{
combinedNumbersInputFile.close ();
ofstream combinedNumbersInputCreateFile ( "Combined Numbers - File 02.txt" );
combinedNumbersInputCreateFile.close ();
combinedNumbersInputFile.open ( "Combined Numbers - File 02.txt" );
}
combinedNumbersInputFile.getline ( combinedNumberCharacterArray , 20 );
for ( int i = 0; !combinedNumbersInputFile.eof (); i++ )
{
if ( !isInserted && combinedNumber <= characterArrayToDecimal ( combinedNumberCharacterArray ) )
{
combinedNumbersOutputFile << combinedNumber << endl;
isInserted = true;
}
combinedNumbersOutputFile << combinedNumberCharacterArray << endl;
combinedNumbersInputFile.getline ( combinedNumberCharacterArray , 20 );
}
if ( !isInserted )
{
combinedNumbersOutputFile << combinedNumber << endl;
isInserted = true;
}
isFirstCombinedFileActive = !isFirstCombinedFileActive;
combinedNumbersOutputFile.close ();
combinedNumbersInputFile.close ();
}
Run Code Online (Sandbox Code Playgroud)
您真正需要的是针对此类问题的分而治之算法。查看外部排序中的外部合并排序和分布排序部分
其想法是将数据排序为多个块,然后使用分而治之的方法再次合并这些块。
它的时间复杂度为O(n logn),我认为会超过时间限制。
这些算法非常有名,你可以通过谷歌搜索来获取实现细节。