Мне был задан этот вопрос на собеседовании:
Для входного файла с четырьмя миллиардами целых чисел предоставьте алгоритм для генерации целого числа, которого нет в файле. Предположим, у вас 1 ГБ памяти. Последуйте за тем, что бы вы сделали, если бы у вас было всего 10 МБ памяти.
Мой анализ:
Размер файла 4 × 10 9 × 4 байта = 16 ГБ.
Мы можем выполнять внешнюю сортировку, тем самым давая нам знать диапазон целых чисел.
Мой вопрос: как лучше всего обнаружить недостающее целое число в отсортированных больших целочисленных наборах?
Мое понимание (после прочтения всех ответов):
Предполагая, что мы говорим о 32-битных целых числах, существует 2 32 = 4 * 10 9 различных целых чисел.
Случай 1: у нас есть 1 ГБ = 1 * 10 9 * 8 бит = 8 миллиардов бит памяти.
Решение:
Если мы используем один бит, представляющий одно целое число, этого достаточно. нам не нужна сортировка.
Реализация:
int radix = 8;
byte[] bitfield = new byte[0xffffffff/radix];
void F() throws FileNotFoundException{
Scanner in = new Scanner(new FileReader("a.txt"));
while(in.hasNextInt()){
int n = in.nextInt();
bitfield[n/radix] |= (1 << (n%radix));
}
for(int i = 0; i< bitfield.lenght; i++){
for(int j =0; j<radix; j++){
if( (bitfield[i] & (1<<j)) == 0) System.out.print(i*radix+j);
}
}
}
Случай 2: 10 МБ памяти = 10 * 10 6 * 8 бит = 80 миллионов бит
Решение:
Для всех возможных 16-битных префиксов имеется 2 16 целых чисел = 65536, нам нужно 2 16 * 4 * 8 = 2 миллиона бит. Нам нужно построить 65536 ведер. Для каждой корзины нам нужно 4 байта, содержащие все возможности, потому что в худшем случае все 4 миллиарда целых чисел принадлежат одной и той же корзине.
- Постройте счетчик каждого ведра при первом проходе через файл.
- Сканируйте ведра, найдите первого, у которого меньше 65536 попаданий.
- Создавайте новые сегменты, чьи высокие 16-битные префиксы находятся на шаге 2 через второй проход файла.
- Просканируйте ведра, построенные на шаге 3, найдите первое ведро, в котором нет попаданий.
Код очень похож на приведенный выше.
Вывод: мы уменьшаем объем памяти за счет увеличения прохода файлов.
Уточнение для опоздавших: вопрос в том виде, в каком он задан, не говорит о том, что есть ровно одно целое число, которое не содержится в файле, по крайней мере, это не так, как его интерпретируют большинство людей. Однако многие комментарии в ветке комментариев относятся к этому варианту задачи. К сожалению, комментарий, который представил его в ветке комментариев, был позже удален его автором, так что теперь похоже, что осиротевшие ответы на него просто все неправильно поняли. Это очень сбивает с толку, извините.
O(n)
время за 10 МБ. - person Paul   schedule 23.08.2011return false
. - person trashgod   schedule 23.08.2011int getMissingNumber(File inputFile) { return 4; }
(ссылка) - person johnny   schedule 23.08.20112^32 - 1
в целом числе, которое может хранить только значения до2^32 - 1
? Вам понадобится 64-битное целое число (или два 32-битных целых числа) для хранения результата. - person Brian Gordon   schedule 23.08.2011n(n-1)/2
, который избавляет нас от необходимости слишком много думать об этом. - person Brian Gordon   schedule 23.08.2011