Цель: создать функцию
hasPairWithSum(arr, sum)
, которая проверяет, существует ли в массивеarr
пара чисел, сумма которых равнаsum
. Решение должно иметь временную сложность O(n).
Наивное решение «в лоб» с двумя вложенными циклами будет иметь квадратичную сложность O(n²), что не удовлетворяет условию. Чтобы достичь линейной сложности O(n), нужно избежать вложенных циклов.
Подумайте, как можно запоминать уже просмотренные числа, чтобы для каждого нового числа быстро проверять, встречалось ли нам ранее «дополнение» до нужной суммы. Какая структура данных позволяет делать проверку на наличие элемента за константное время O(1)?
const hasPairWithSum = (arr, sum) => {
// Создаем Set для хранения чисел, которые мы уже видели.
// Set обеспечивает очень быстрый поиск (в среднем O(1)).
const seenNumbers = new Set();
// Проходим по каждому числу в исходном массиве.
for (const num of arr) {
// Для каждого числа `num` вычисляем "дополнение" (`complement`),
// то есть число, которое в сумме с `num` даст `sum`.
const complement = sum - num;
// Проверяем, есть ли это "дополнение" в нашем Set'е.
// Если да, значит, мы нашли пару.
if (seenNumbers.has(complement)) {
return true; // Пара найдена, немедленно выходим из функции.
}
// Если "дополнение" не найдено, добавляем текущее число `num` в Set.
// Это нужно, чтобы последующие числа могли "найти" его в качестве своего дополнения.
seenNumbers.add(num);
}
// Если мы прошли весь массив и не нашли ни одной пары,
// значит, ее нет. Возвращаем false.
return false;
};
Почему именно так:
Set
для скорости: Операции добавления (add
) и проверки наличия (has
) в Set
в среднем выполняются за константное время O(1). Это позволяет нам для каждого элемента массива мгновенно проверять, встречали ли мы уже число, которое в сумме с текущим даст sum
.num
из массива мы вычисляем, какое число complement
нам нужно, чтобы получить sum
. Затем мы проверяем, есть ли complement
в нашем Set
’е. Если да — мы нашли пару, и можно возвращать true
. Если нет — добавляем текущее число num
в Set
и переходим к следующему элементу. Если мы прошли весь массив и не нашли пару, возвращаем false
.Set
может хранить все элементы массива.const hasPairWithSum = (arr, sum) => {
// Сортируем массив. Сложность O(n log n)
const sortedArr = [...arr].sort((a, b) => a - b);
let left = 0;
let right = sortedArr.length - 1;
// Проходим по массиву с двух концов. Сложность O(n)
while (left < right) {
const currentSum = sortedArr[left] + sortedArr[right];
if (currentSum === sum) {
return true; // Нашли пару
} else if (currentSum < sum) {
left++; // Сумма слишком мала, двигаем левый указатель вправо
} else {
right--; // Сумма слишком велика, двигаем правый указатель влево
}
}
return false; // Пара не найдена
};
Почему именно так:
arr.sort()
), то дополнительная память почти не требуется (зависит от реализации sort
). В примере мы создаем копию, что дает O(n), но это можно оптимизировать.Вам нужно реализовать функцию hasPairWithSum
, которая принимает на вход два аргумента:
arr
— массив (коллекция) чисел.sum
— целевая сумма.Функция должна вернуть true
, если в массиве arr
существует два элемента, сумма которых в точности равна sum
. В противном случае функция должна вернуть false
.
// Находит пару (4 + 4 = 8)
hasPairWithSum([1, 4, 4, 9], 8); // true
// Пары, дающей 8, нет
hasPairWithSum([3, 4, 7, 10], 8); // false
// Находит пару (-8 + 16 = 8)
hasPairWithSum([-8, 1, 4, 9, 16], 8); // true
hasPairWithSum
.true
или false
).Цель: создать функцию
hasPairWithSum(arr, sum)
, которая проверяет, существует ли в массивеarr
пара чисел, сумма которых равнаsum
. Решение должно иметь временную сложность O(n).
Наивное решение «в лоб» с двумя вложенными циклами будет иметь квадратичную сложность O(n²), что не удовлетворяет условию. Чтобы достичь линейной сложности O(n), нужно избежать вложенных циклов.
Подумайте, как можно запоминать уже просмотренные числа, чтобы для каждого нового числа быстро проверять, встречалось ли нам ранее «дополнение» до нужной суммы. Какая структура данных позволяет делать проверку на наличие элемента за константное время O(1)?
const hasPairWithSum = (arr, sum) => {
// Создаем Set для хранения чисел, которые мы уже видели.
// Set обеспечивает очень быстрый поиск (в среднем O(1)).
const seenNumbers = new Set();
// Проходим по каждому числу в исходном массиве.
for (const num of arr) {
// Для каждого числа `num` вычисляем "дополнение" (`complement`),
// то есть число, которое в сумме с `num` даст `sum`.
const complement = sum - num;
// Проверяем, есть ли это "дополнение" в нашем Set'е.
// Если да, значит, мы нашли пару.
if (seenNumbers.has(complement)) {
return true; // Пара найдена, немедленно выходим из функции.
}
// Если "дополнение" не найдено, добавляем текущее число `num` в Set.
// Это нужно, чтобы последующие числа могли "найти" его в качестве своего дополнения.
seenNumbers.add(num);
}
// Если мы прошли весь массив и не нашли ни одной пары,
// значит, ее нет. Возвращаем false.
return false;
};
Почему именно так:
Set
для скорости: Операции добавления (add
) и проверки наличия (has
) в Set
в среднем выполняются за константное время O(1). Это позволяет нам для каждого элемента массива мгновенно проверять, встречали ли мы уже число, которое в сумме с текущим даст sum
.num
из массива мы вычисляем, какое число complement
нам нужно, чтобы получить sum
. Затем мы проверяем, есть ли complement
в нашем Set
’е. Если да — мы нашли пару, и можно возвращать true
. Если нет — добавляем текущее число num
в Set
и переходим к следующему элементу. Если мы прошли весь массив и не нашли пару, возвращаем false
.Set
может хранить все элементы массива.const hasPairWithSum = (arr, sum) => {
// Сортируем массив. Сложность O(n log n)
const sortedArr = [...arr].sort((a, b) => a - b);
let left = 0;
let right = sortedArr.length - 1;
// Проходим по массиву с двух концов. Сложность O(n)
while (left < right) {
const currentSum = sortedArr[left] + sortedArr[right];
if (currentSum === sum) {
return true; // Нашли пару
} else if (currentSum < sum) {
left++; // Сумма слишком мала, двигаем левый указатель вправо
} else {
right--; // Сумма слишком велика, двигаем правый указатель влево
}
}
return false; // Пара не найдена
};
Почему именно так:
arr.sort()
), то дополнительная память почти не требуется (зависит от реализации sort
). В примере мы создаем копию, что дает O(n), но это можно оптимизировать.Вам нужно реализовать функцию hasPairWithSum
, которая принимает на вход два аргумента:
arr
— массив (коллекция) чисел.sum
— целевая сумма.Функция должна вернуть true
, если в массиве arr
существует два элемента, сумма которых в точности равна sum
. В противном случае функция должна вернуть false
.
// Находит пару (4 + 4 = 8)
hasPairWithSum([1, 4, 4, 9], 8); // true
// Пары, дающей 8, нет
hasPairWithSum([3, 4, 7, 10], 8); // false
// Находит пару (-8 + 16 = 8)
hasPairWithSum([-8, 1, 4, 9, 16], 8); // true
hasPairWithSum
.true
или false
).Редактор кода намеренно скрыт на мобильном.
Поверь, так лучше: я оберегаю тебя от искушения писать код в неидеальных условиях. Маленький экран и виртуальная клавиатура — не лучшие помощники для программиста.
📖 Сейчас: Изучи задачу, продумай решение. Действуй как стратег.
💻 Потом: Сядь за компьютер, открой сайт и реализуй все идеи с комфортом. Действуй как код-джедай!