Problem Statement
I'm given a very large list of numbers one at a time, and I need to print the "median number".
To be more clear there can be "125,000,000" numbers and it is guaranteed that each number is less than "1.e+18".
It's for a contest, so there is memory limit (20 MB tops) and time limit (5 seconds tops).
"The median number" is the one that is in the middle of sorted numbers.
For instance if this is the list of numbers:
23
8
16
42
15
4
108
After sorting numbers:
1) 4
2) 8
3) 15
4) 16
5) 23
6) 42
7) 108
"The median number" would be 16;
So I searched for it in the Internet but I couldn't find any answer that pass these limits.
Approach
My approach was to get all the numbers, save them in a text file, sort them, then get "the median number".
Ideas
- I know I can read all the numbers from the file and put them in a vector
then easily sort them.
But this will exceed memory limit. - So I came up with this idea to sort numbers as I put them in text
file.
It would be like there is a loop that after getting next number from the console reads the file (line by line) and when it reaches right place, inserts number there and doesn't touch other numbers.
But the problem is that I can't insert a line in the middle of text file because it will overwrite on other numbers. - So I created two files that one of them had numbers that were already
inputted and the other one read the first file and copy it's number in
itself until reach right place then insert last given number then
continue copying remaining numbers.
But it spends too much time so it exceeded time limit.
Request
So I want to either optimize one of these ideas in order to pass limits or any new idea that pass these limits.
Preference
I prefer to use second idea because unlike other two, it passes limits but I can't do it because I don't know how to insert a line in the middle of a text file. So if I learn this, rest of the process will be so easy.
Attempted Solution
This is a function that receives a number and, by reading through a file, finds best place for it and puts it there.
As the matter of fact it represents my third idea.
So it works (I tested it with lots of inputs) but the problem as I mentioned before is with the time limit.
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 ();
}