> Как устроено решение задачи поиска пары чисел с заданной суммой (JavaScript)

Уровень: senior · Роль: frontend · Язык: JavaScript · Категория: Кодинг

Компании: ЭНИРАН

Стек: Node.js, JavaScript

> Пример ответа

Короткий ответ

Задача сводится к поиску двух элементов массива, сумма которых равна заданному числу. Оптимальное решение - использовать хеш-таблицу (Set или Map) для хранения уже просмотренных значений. Сложность по времени - O(n), по памяти - O(n). Альтернативный вариант с двумя указателями требует предварительной сортировки массива, что даёт O(n log n) по времени и O(1) по памяти (без учёта сортировки). Для frontend-задач обычно ожидают именно хеш-таблицу.

Подход к решению

Основная идея: для каждого элемента current ищем комплемент target - current в структуре данных. Если комплемент уже встречался - возвращаем индексы или значения. Иначе добавляем текущий элемент в структуру.

Варианты реализации:

  • Set - если нужны только значения, не индексы.
  • Map - если нужны индексы (храним значение → индекс).
  • Два указателя - после сортировки массива, двигаем указатели с концов к центру. Подходит, если допустимо изменять порядок элементов.

Для Node.js важно учитывать, что операция has/get в Set/Map - O(1) в среднем. При больших массивах стоит избегать indexOf внутри цикла - это даст O(n²).

Пример кода

JAVASCRIPT
function findPairWithSum(arr, target) {
const seen = new Map();
for (let i = 0; i < arr.length; i++) {
const complement = target - arr[i];
if (seen.has(complement)) {
return [seen.get(complement), i];
}
seen.set(arr[i], i);
}
return null;
}
// Пример использования
const nums = [2, 7, 11, 15];
const target = 9;
console.log(findPairWithSum(nums, target)); // [0, 1]

Вариант с двумя указателями:

JAVASCRIPT
function findPairWithSumSorted(arr, target) {
const sorted = [...arr].sort((a, b) => a - b);
let left = 0;
let right = sorted.length - 1;
while (left < right) {
const sum = sorted[left] + sorted[right];
if (sum === target) return [sorted[left], sorted[right]];
if (sum < target) left++;
else right--;
}
return null;
}

Edge cases

  • Пустой массив - возвращаем null.
  • Массив из одного элемента - null.
  • Отрицательные числа - работают корректно, комплемент может быть отрицательным.
  • Дубликаты - Map перезапишет индекс, но это не проблема, если нужна любая пара.
  • Нет пары - возвращаем null (или throw, зависит от контекста).
  • Очень большие числа - сумма может выйти за пределы Number.MAX_SAFE_INTEGER, стоит использовать BigInt, если это критично.
  • Массив не отсортирован - для двух указателей нужна сортировка, для Map - нет.

Как отвечать на собеседовании

Начните с уточнения: нужны индексы или значения? Можно ли изменять массив? Есть ли ограничения по памяти? Затем предложите наивное решение (двойной цикл) и объясните, почему оно неоптимально. После этого переходите к хеш-таблице, акцентируя trade-off между временем и памятью. Если спросят про два указателя - упомяните, что это требует сортировки, но экономит память. В конце обязательно проговорите сложность и edge cases. Не пишите код сразу - сначала опишите алгоритм словами.

Что проверяет интервьюер

  • Понимание базовых структур данных (Map, Set) и их временной сложности.
  • Умение анализировать trade-off между временем и памятью.
  • Внимание к деталям: индексы vs значения, дубликаты, отрицательные числа.
  • Способность объяснить алгоритм до написания кода.
  • Знание особенностей JavaScript: числовые ограничения, поведение Map с примитивами.
  • Для senior-позиции - умение обсудить масштабируемость: что будет при миллионе элементов, как оптимизировать под конкретный use case.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью