> Как удалить дубликаты из массива чисел и строк без использования Set в JavaScript? (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Tilda
Стек: JavaScript
> Пример ответа
Короткий ответ
Удалить дубликаты можно через filter с indexOf, reduce с аккумулятором-массивом, или через объект-хэш (Map). Для чисел и строк подходит хэш-подход: проходим по массиву, сохраняем уникальные ключи в объекте и возвращаем только те элементы, которые встретились впервые. Это O(n) по времени и O(n) по памяти.
Подробное объяснение
Основная задача - сохранить порядок элементов и эффективно проверять уникальность. Set даёт O(1) на проверку, но без него нужно реализовать аналогичную структуру. Подходы различаются по производительности:
- filter + indexOf: O(n²), так как indexOf проходит по массиву каждый раз. Подходит только для маленьких массивов.
- reduce + includes: тоже O(n²), includes - линейный поиск.
- Объект-хэш: O(n). Используем свойства объекта (или Map) как хэш-таблицу. Ключом может быть сам элемент (для строк и чисел это безопасно). Проверяем, есть ли ключ, если нет - добавляем в результат и устанавливаем ключ.
- Map: предпочтительнее объекта, так как не наследует прототипные ключи и сохраняет тип ключа (число vs строка "1").
Важно: для смешанных типов (числа и строки) объект может привести к коллизиям, если число и строка с одинаковым значением (например, 1 и "1") считаются разными. В таком случае используем Map или храним ключи с префиксом типа.
На практике
В реальных проектах Set - стандартное решение. Но если задача стоит без Set, выбираем хэш-подход с Map для надёжности. Для массивов до 1000 элементов можно использовать filter + indexOf, но это медленнее. Важно учитывать, что NaN и undefined требуют особой обработки: indexOf не найдёт NaN, а объект-хэш может их потерять.
Пример кода
JAVASCRIPT// Хэш-подход с Map (рекомендуемый)function removeDuplicates(arr) {const seen = new Map();const result = [];for (const item of arr) {if (!seen.has(item)) {seen.set(item, true);result.push(item);}}return result;}// filter + indexOf (O(n²), для маленьких массивов)function removeDuplicatesSimple(arr) {return arr.filter((item, index) => arr.indexOf(item) === index);}// reduce + includes (тоже O(n²))function removeDuplicatesReduce(arr) {return arr.reduce((acc, item) => {if (!acc.includes(item)) acc.push(item);return acc;}, []);}// Пример с учётом типов (число 1 и строка "1" - разные)function removeDuplicatesTyped(arr) {const seen = new Map();return arr.filter(item => {const key = typeof item + ':' + item;if (seen.has(key)) return false;seen.set(key, true);return true;});}
Как отвечать на собеседовании
Начни с краткого ответа, затем объясни trade-off между подходами. Упомяни, что filter + indexOf - это квадратичная сложность, а хэш-подход - линейная. Подчеркни, что для смешанных типов нужен Map или префикс типа. Если спросят про NaN, скажи, что indexOf не работает, а хэш-подход с Map корректно обрабатывает NaN (Map использует SameValueZero). Покажи пример кода с Map как наиболее универсальный.
Что проверяет интервьюер
- Понимание алгоритмической сложности (O(n) vs O(n²)).
- Умение реализовать хэш-таблицу вручную.
- Знание особенностей типов в JavaScript (число vs строка, NaN).
- Способность выбирать оптимальное решение под контекст.
Типичные ошибки
- Использование объекта без проверки hasOwnProperty (может вернуть ложные срабатывания на прототипные ключи, например,
toString). - Игнорирование различий между 1 и "1" - объект приводит ключи к строке, поэтому 1 и "1" считаются одинаковыми.
- Забывают про NaN:
indexOfне находит NaN, а объект-хэш может его потерять. - Мутация исходного массива вместо возврата нового.
- Использование
deleteна объекте-хэше в цикле - это ломает производительность.
> Похожие задачи по frontend
Как улучшить сигнатуру функции, чтобы избежать передачи undefined?
Как проходят таски в event loop
Как реализуется инкапсуляция в JavaScript
Как управлять очередностью загрузки и выполнения скриптов в JavaScript
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью