Как двигать левый и правый указатели в зависимости от суммы при поиске пары чисел?
Что проверяют
Понимаете ли вы, почему метод двух указателей корректен, а не просто помните шаблон. Следом спрашивают про сложность, про неотсортированный массив и про то, как вернуть индексы, а не значения.
Как отвечать
Метод работает только на массиве, отсортированном по возрастанию. Ставим left = 0 и right = arr.length - 1 и смотрим на сумму:
- сумма равна цели: пара найдена;
- сумма меньше цели: сдвигаем
leftвправо. Уменьшатьrightбессмысленно, сумма от этого только упадёт; - сумма больше цели: сдвигаем
rightвлево по той же логике; - условие цикла:
while (left < right), чтобы не сложить элемент сам с собой.
function findPair(arr, target) {
let left = 0, right = arr.length - 1;
while (left < right) {
const sum = arr[left] + arr[right];
if (sum === target) return [arr[left], arr[right]];
if (sum < target) left++; else right--;
}
return null;
}Почему ничего не теряется: если сумма меньше цели, arr[left] не даёт пары ни с одним оставшимся элементом, ведь даже с самым большим не хватает. Его можно отбросить навсегда. Этот инвариант и стоит проговорить.
Сложность: O(n) по времени и O(1) по памяти на отсортированном массиве. Если массив не отсортирован, сортировка добавляет O(n log n), и тогда выгоднее хэш-подход через Map за O(n): для каждого числа проверяем, встречалось ли target - x. Он же сохраняет исходные индексы.
Где спотыкаются
Сортируют через arr.sort() без компаратора. В JavaScript это сортировка строк: [10, 15, 3, 7].sort() вернёт [10, 15, 3, 7], и алгоритм тихо ломается. Нужно sort((a, b) => a - b), а чтобы не портить входной массив, toSorted.
Сдвигают оба указателя сразу или двигают не тот. Помогает вслух повторить правило: сумма мала, растим левый.
Возвращают индексы после сортировки, хотя задача просила индексы исходного массива. Сортировка их перемешала, нужен либо Map, либо сортировка пар «значение, индекс».