Предположим, у вас есть аккумулятор
int accumulator = 0;
На каждом шаге вашего цикла вы XOR аккумулятор с i
и v
, где i
- это индекс итерации цикла, а v
- это значение в i
-ой позиции массив.
accumulator ^= (i ^ v)
Обычно i
и v
будут одним и тем же числом, поэтому вы в конечном итоге выполните
accumulator ^= (i ^ i)
Но i ^ i == 0
, так что это в конечном итоге не будет, и значение аккумулятора останется нетронутым. На этом этапе я должен сказать, что порядок чисел в массиве не имеет значения, потому что XOR является коммутативным, поэтому, даже если массив перетасовывается для начала с результатом в конце, он все равно должен быть 0
(начальное значение аккумулятор).
А что если число встречается в массиве дважды? Очевидно, что это число будет появляться три раза в XORing (один для индекса, равного числу, один для обычного появления числа и один для дополнительного появления). Кроме того, одно из других чисел появится только один раз (только для его индекса).
Это решение теперь предполагает, что число, которое появляется только один раз, равно последнему индексу массива или, другими словами: диапазон чисел в массиве является смежным и начинается с первого обрабатываемого индекса ( edit: спасибо caf для этого хедз-ап комментария, это то, что я действительно имел в виду, но я полностью испортил это, когда писал ). С этим (N
появляется только один раз) как данность, учтите, что начиная с
int accumulator = N;
эффективно заставляет N
снова появляться дважды в XORing. На данный момент у нас осталось чисел, которые появляются только ровно дважды, и только одно число, которое появляется три раза . Так как дважды появившиеся числа будут XOR равны 0, конечное значение аккумулятора будет равно числу, которое появляется три раза (то есть одно дополнительное).