Ответ
Временная сложность классического полного перебора с двумя вложенными циклами, каждый из которых зависит от размера входных данных n, составляет O(n²) (квадратичная сложность).
Пример на JavaScript/Node.js:
// O(n²)
for (let i = 0; i < n; i++) { // Внешний цикл: O(n)
for (let j = 0; j < n; j++) { // Внутренний цикл: O(n)
// Какая-то операция O(1)
console.log(`Pair: ${i}, ${j}`);
}
}
// Общее количество итераций: n * n = n²
Вариации:
- Если размеры массивов разные (
nиm), сложность будет *O(n m)**.// O(n * m) const arr1 = new Array(n); const arr2 = new Array(m); for (let i = 0; i < arr1.length; i++) { for (let j = 0; j < arr2.length; j++) { // Операция } } - Если внутренний цикл начинается с
i+1(например, для сравнения всех уникальных пар), сложность остаётся O(n²), но количество итераций будет примерноn²/2, что в асимптотическом анализе всё равно O(n²).
Квадратичная сложность считается неэффективной для больших данных, и в production-коде на Node.js для подобных задач часто ищут оптимизации (кеширование, хеш-таблицы, более эффективные алгоритмы).
Ответ 18+ 🔞
Смотри, тут всё просто, как три копейки. Если у тебя в коде сидят два цикла, один в другом, и оба гоняются по всему массиву размером n — это классический пиздец, который мы называем O(n²). Квадратичная сложность, ёпта. Это когда твой алгоритм жрёт ресурсы, как не в себя, и на больших данных начинает тормозить так, что хоть святых выноси.
Вот тебе наглядный пример на Node.js, чтобы не было вопросов:
// O(n²)
for (let i = 0; i < n; i++) { // Внешний цикл: O(n)
for (let j = 0; j < n; j++) { // Внутренний цикл: O(n)
// Какая-то операция O(1)
console.log(`Pair: ${i}, ${j}`);
}
}
// Общее количество итераций: n * n = n²
Видишь? Каждый раз, когда внешний цикл делает шаг, внутренний пробегает весь массив снова. Получается n раз по n итераций. Это и есть тот самый квадрат, от которого потом волосы дыбом встают.
Но жизнь, она же хитрая жопа, бывают нюансы:
- Если массивы разного размера (
nиm), то сложность будет *O(n m)**. Не квадрат, конечно, но тоже не подарок.// O(n * m) const arr1 = new Array(n); const arr2 = new Array(m); for (let i = 0; i < arr1.length; i++) { for (let j = 0; j < arr2.length; j++) { // Операция } } - Бывает, внутренний цикл стартует не с нуля, а с
i+1(чтобы сравнить все уникальные пары). Количество операций упадёт примерно вдвое, доn²/2, но в большой нотации O(n²) это всё равно считается. Потому что константы (типа деления на 2) на асимптотику, блядь, не влияют.
Короче, запомни: если видишь вложенные циклы по одним и тем же данным — это красная лампочка. В продакшене на Node.js такую хуйню обычно стараются переписать: использовать хеш-таблицы, кеширование или ещё какую умную оптимизацию, чтобы не получить овердохуища запросов и не накрыться медным тазом.