Учитывая файл, содержащий 4,30 миллиарда 32-разрядных целых чисел, как мы можем найти число, которое появилось как минимум дважды?
Я придумал алгоритм "разделяй и властвуй" для этого. Просто хотел узнать, сработает ли это или нет?
Первая середина вычисляется из целочисленного диапазона, т.е. (0+(1<<32-1))>>1, а затем применяется эта идея: диапазон чисел от начала до середины или от середины до конца всегда будет меньше чисел мы рассмотрим, как мы рассматриваем миллиардные числа, и определенно найдутся некоторые числа, которые будут повторяться, так как диапазон 32-битного целого числа намного меньше по сравнению с миллиардным числом.
def get_duplicate(input, start, end):
while True:
mid = (start >> 1) + end - (end >> 1)
less_to_mid = 0
more_to_mid = 0
equal_to_mid = 0
for data in input:
data = int(data, 16)
if data < mid:
less_to_mid += 1
elif data == mid:
equal_to_mid += 1
else:
more_to_mid += 1
if equal_to_mid > 1:
return mid
elif mid-start < less_to_mid:
end = mid-1
elif end-mid < more_to_mid:
start = mid+1
with open("codes\output.txt", 'r+') as f:
content = f.read().split()
print(get_duplicate(content, 0, 1<<32-1))
Я знаю, что мы можем использовать битовый массив, но я просто хочу узнать ваше мнение об этом решении, и если реализация содержит ошибки.
2 ответа
Ваш метод в порядке. Но вам, вероятно, нужно будет прочитать ввод много раз, чтобы найти ответ.
Вот вариант, который позволяет вам найти дубликат с небольшим объемом памяти, но вам нужно только прочитать вход дважды.
- Инициализировать массив
A[65536]
целых чисел в ноль. - Читайте цифры по одному. Каждый раз, когда число
x
читать, добавить1
вA[x mod 65536]
, - Когда чтение закончится, появится хотя бы один
i
такой, чтоA[i]
строго больше, чем65536
, Это потому что65536 * 63356 < 4.3 billion
, СкажемA[i0]
больше чем65536
, - Очистить массив
A
в ноль. - Прочитайте цифры еще раз, но на этот раз, только посмотрите на эти цифры
x
такой, чтоx mod 65536 = i0
, За каждый такойx
, добавлять1
вA[x / 65536]
, - Когда чтение закончится, появится хотя бы один
j
такой, чтоA[j]
строго больше, чем1
, Тогда число65536 * j + i0
это окончательный ответ.
Память размером 2^32 бита не является чем-то особенным для современных систем. Так что вы должны использовать bitset
этой структуре данных нужно только немного на число, и у всех современных языков есть реализация. Идея в том, что вы просто помните, был ли номер уже виден:
void print_twice_seen (Iterator &it)//iterates through all numbers
{
std::bitset< (1L<<32) > seen;//bitset for 2^32 elements, assume 64bit system
while(it.hasNext()){
unsigned int val=it.next();//return current element and move the iterator
if(seen[val])
std::cout<<"Seen at least twice: "<<val<<std::endl;
else
seen.set(val, true);//remember as seen
}
}