int FindSingleNumber(const vector<int>& nums) {
int result = 0;
for (int n : nums) {
result ^= n;
}
return result;
}
Такой способ позволяет решить за O(n) по времени и O(1) по памяти.
Это возможно с помощью оператора XOR — исключающее ИЛИ.
Числа состоят из байтов, а байты из битов. XOR работает с битами двух чисел и возвращает в результате третье число. Операция производится поразрядно по одному биту из каждого числа.
XOR вернёт 1, если только один бит равен 1. Получится вот так:
A B C
0 0 0
1 0 1
0 1 1
1 1 0
На примере вот такого вектора:
{12, 11, 12} рассмотрим что будет происходить. Покажем только 4 первых бита:Изначально
result равен нулю, значит:0 ^ 12 — 0000 ^ 1100 = 11001100 ^ 11 — 1100 ^ 1011 = 01110111 ^ 12 — 0111 ^ 1100 = 1011В конце получился
1011, это 11 в двоичной системе исчисления.Первое число просто присвоилось переменной
result, а далее биты другого числа вычитались из него. После второго числа в переменной было число 0111 — число 7. Если бы не условие, что все числа будут повторяться дважды, кроме одного, то наличие числа 7 в векторе всё бы испортило и превратило число назад в 0. Второе повторение того же числа (необязательно даже последовательное) отменяет первую операцию. А так как одно число повторяется только один раз, то его никто не компенсировал, и оно осталось храниться в результате.Битовые операции используются в разных трюках. Попробуйте решить эту задачу менее оптимальным способом по памяти, например с использованием множества или словаря.