Интервьюшную загадку заганули - Playing poohsticks in the Styx — LiveJournal
Apr. 14th, 2016
09:28 am - Интервьюшную загадку заганули
Дан массив целых неотрицательных чисел. Требуется как можно эффективнее найти сумму попарных хэмминговых расстояний между ними.
Upd: Раскрыл все комменты. Ожидаемый ответ был эквивалентен этому
Видимо, при использовании пирамидальной схемы с битовыми трюками, это можно сделать за O(n+b).
В классическом виде алгоритм подсчета бит, который рассматривает слово как массив N однобитных чисел, делит на два массива по N/2 2-битных чисел, складывает и т.д. использует числовое пространство неэффективно. То есть, например, для 32-битного слова после
a = (a & 0x55555555) + ((a>>1) & 0x55555555)
каждое 2-битное число может хранить значения вплоть до 3, а на самом деле они окажутся не больше 2. Поэтому туда можно добавить еще одну половинку расслоенного числа, которая потом пойдет обрабатываться дальше "забесплатно". Если в процессоре есть достаточно регистров, можно выстроить целую пирамиду таких частичных результатов, которые будут добавляться по мере возможности. Xраниться будут что-нибудь типа 32-битного числа/массива (64 бит не надо, у нас нет столько чисел в массиве, и вообще верхнюю категорию достаточно log2(arraysize)), 16-битного, 8-битного, 4-битного, 2-битного, остающейся второй половинки 2-битного.
Но оптимальный порядок сложения будет запутанным, про него надо подумать отдельно.
Edited at 2016-04-15 07:57 am (UTC)
В процессе прохождения массива, надо накапливать частичные суммы, а также делать ХOR всех накопленных пар по диагонали.
Вот пример для массива {a,b,c,d}
1. a^b
2. a^b^c, b^c
3. a^b^c^d, b^c^d, c^d
В процессе делаем XOR пар по диагонали
(a^b)^(b^c)=a^c
(a^b^c)^(b^c^d)=a^d
(b^c)^(c^d)=b^d