> Как оптимизировать алгоритм поиска уникального элемента без дополнительной памяти (PHP)
Уровень: senior · Роль: backend · Язык: PHP · Категория: Технические вопросы
Компании: Travelata
Стек: PHP
> Пример ответа
Короткий ответ
Оптимальный способ - XOR-свертка всех элементов массива. Поскольку a ^ a = 0 и 0 ^ a = a, парные элементы взаимно уничтожаются, а уникальный остаётся. Сложность O(n) по времени и O(1) по памяти. В PHP это делается циклом foreach с оператором ^. Альтернатива для строк - суммирование по байтам, но XOR универсален для целых чисел и не зависит от порядка элементов.
Подробное объяснение
Задача: в массиве все элементы встречаются ровно дважды, кроме одного - его нужно найти без использования дополнительных структур данных (массивов, hash-таблиц, множеств).
Ключевое свойство XOR: операция коммутативна, ассоциативна, и x ^ x = 0. При последовательном применении XOR ко всем элементам парные значения сокращаются. Результат - искомый уникальный элемент.
Почему это работает для любых целых чисел, включая отрицательные и PHP-строки (при приведении к int)? Потому что XOR оперирует на битовом уровне, и сокращение пар не зависит от порядка.
Ограничения: метод применим только когда уникальный элемент ровно один и все остальные встречаются ровно дважды. Если условие другое (например, три вхождения), XOR не подойдёт - тогда потребуется сортировка или подсчёт с дополнительной памятью.
На практике
В PHP для больших массивов важно избегать array_reduce с замыканием - он создаёт накладные расходы на вызов функции для каждого элемента. Простой foreach с локальной переменной быстрее.
Для строк или смешанных данных можно привести к целому через ord() или unpack(), но это редко нужно - обычно задача даётся для целых чисел.
Если массив ассоциативный, ключи игнорируются, работаем только со значениями.
Пример кода
PHPfunction findUnique(array $arr): int{$result = 0;foreach ($arr as $value) {$result ^= $value;}return $result;}// Пример использования$data = [4, 1, 2, 1, 2];echo findUnique($data); // 4
Для строк (если гарантированно один уникальный символ):
PHPfunction findUniqueChar(string $s): string{$result = 0;$len = strlen($s);for ($i = 0; $i < $len; $i++) {$result ^= ord($s[$i]);}return chr($result);}
Как отвечать на собеседовании
Начните с уточнения условий: "Предполагаю, что все элементы кроме одного встречаются ровно дважды". Затем предложите наивное решение (hash-таблица) и объясните его недостаток - O(n) памяти. После этого переходите к XOR, подчеркнув битовую природу операции. Обязательно упомяните сложность O(n) по времени и O(1) по памяти.
Если интервьюер спрашивает про альтернативы - упомяните сортировку (O(n log n), но без дополнительной памяти) и суммирование (не работает для отрицательных чисел и переполнений). XOR - самый элегантный вариант.
Что проверяет интервьюер
- Понимание битовых операций и их свойств.
- Умение оценивать сложность алгоритмов по времени и памяти.
- Способность видеть неочевидные решения (XOR вместо hash-таблицы).
- Практические знания PHP: производительность циклов, особенности работы с типами.
- Внимательность к деталям: корректность для пустого массива, отрицательных чисел, больших значений.
Типичные ошибки
- Использование
array_count_valuesилиarray_flip- это дополнительная память O(n). - Применение XOR к строкам без преобразования - PHP приведёт строку к int, что даст неверный результат.
- Забывают про случай пустого массива - вернётся 0, хотя по условию уникальный элемент должен быть.
- Предлагают суммирование:
array_sum- не работает для отрицательных чисел и может переполниться. - Используют
array_reduceс замыканием - медленнее, чемforeachна больших данных. - Не проверяют, что условие "ровно два вхождения" соблюдено - XOR даст мусор для других кратностей.
> Похожие задачи по PHP
Что произойдет при вызове асинхронной функции без await?
Как устроен жизненный цикл запроса в Symfony
Какие принципы проектирования кроме SOLID существуют
С какими паттернами проектирования ты работал
> Похожие задачи по backend
Что произойдет при вызове асинхронной функции без await?
Как устроен жизненный цикл запроса в Symfony
Какие принципы проектирования кроме SOLID существуют
С какими паттернами проектирования ты работал
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью