Обозначение Big O помогает нам анализировать и сравнивать производительность алгоритмов. В мире алгоритмов «наилучший сценарий» представляет собой наиболее идеальные условия, при которых алгоритм работает с максимальной эффективностью, а «наихудший сценарий» представляет собой наиболее сложные условия, когда алгоритму требуется больше всего времени для выполнения задачи.

Для анализа алгоритмов мы проверяем две сложности: временную и пространственную.

Временная сложность

Временная сложность — это мера того, как время работы алгоритма масштабируется в зависимости от размера входных данных. Это помогает нам сравнивать и анализировать эффективность алгоритмов с точки зрения их производительности в наихудшем случае.

Космическая сложность

Пространственная сложность — это мера того, сколько дополнительной памяти или памяти требуется алгоритму при увеличении размера входных данных.

Содержание

  • O(1) — постоянное время
  • O(logn) — логарифмическое время
  • O(n) — линейное время
  • O(n²) — квадратичное время
  • O(2^n) — Экспоненциальная временная сложность

O(1) — постоянное время

Независимо от размера входных данных, введенных в алгоритм, время, затрачиваемое алгоритмом, фиксировано.

Мы можем привести примеры, как показано ниже;

  • Математические проблемы
  • Поиск значения с индексом в массиве
  • Достичь хеша с помощью ключа

Пример:

В приведенном ниже примере значения timeOfSmallArray и timeOfHugeArray будут рассчитаны одновременно. Следовательно, его сложность равна O(1).

const smallArray  = [1, 2, 3, 4, 5]
const hugeArray = [1, 2, 3, ... 100000000]

fucntion getFirstValueFromArray(array){
    const firstValue = n[0]
    return firstValue
}

let timeOfSmallArray = getFirstValueFromArray(smallArray)
let timeOfHugeArray = getFirstValueFromArray(hugeArray)

O(log n) — логарифмическое время

Это алгоритмы, в которых время алгоритма увеличивается логарифмически при увеличении входных данных алгоритма. Чаще всего он используется в задачах «разделяй и властвуй».

Пример:

В качестве примера из реальной жизни у нас есть массив, содержащий несколько букв, отсортированных в алфавитном порядке, и мы хотим найти данную букву. Сначала он проверит середину букв, находится ли данная буква дальше средней буквы. он проверит правые буквы средней буквы, и так будет до тех пор, пока не будет найдена данная буква.

function findIndexOfLetter(array, letter) {
  let left = 0;
  let right = array.length;

  while (left < right) {
    let middle = Math.ceil((left + right) / 2);

    if (array[middle] > letter) {
      right = middle;
    } else if (array[middle] < letter) {
      left = middle;
    } else {
      return middle;
    }
  }
}

findLetter(["a", "b", "c", "k", "l", "y", "z"], "c"); 
// output: 2

O(N) — линейное время

По мере увеличения входных данных алгоритма затраченное время увеличивается с той же скоростью.

В качестве примера из реальной жизни: если кран наполняет литр за одну минуту, он наполняет десять литров за десять минут и тысячу литров за тысячу минут. Поскольку количество литров приближается к тысячам и миллионам, для меня это становится худшим вариантом (наихудшим вариантом).

В программировании это обычно происходит с такими методами, как forEach, for, Map и Reduc.

Пример:

В приведенном ниже примере функция getFirstValueFromArray(smallArray) будет рассчитана раньше, чем функция getFirstValueFromArray(hugeArray), поскольку количество значений HugeArray больше, чем количество SmallArray.

const smallArray  = [1, 2, 3, 4, 5]
const hugeArray = [1, 2, 3, ... 100000000]

    function showEveryItemFromArray(array){
        for(let i=0; i < array.length; i++){
            console.log(array[i])
        }
    }

let timeOfSmallArray = showEveryItemFromArray(smallArray)
let timeOfHugeArray = showEveryItemFromArray(hugeArray)

O() — квадратичное время

Когда входные данные алгоритма увеличиваются, продолжительность алгоритма увеличивается на квадрат приращения входных данных.

Ситуации большинства базовых алгоритмов сортировки - это O(n²), и для них это наихудший случай алгоритма, как показано в примерах ниже;

  • Алгоритм пузырьковой сортировки
  • Алгоритм сортировки вставками
  • Алгоритм сортировки выбором

Пример:

У нас есть пример наихудшего случая пузырьковой сортировки. Его сложность O(n²). Если входные данные включают 5 элементов и занимают 25 секунд, а если входные данные включают 10 элементов, это займет 100 секунд.

const array = [5, 4, 3, 2, 1];

for (let i = 0; i < array.length; i++) {
  for (let j = 0; j < array.length - i - 1; j++) {
    if (array[j] > array[j + 1]) {
      [array[j], array[j + 1]] = [array[j + 1], array[j]];
    }
  }
}

console.log(array); // Output: [1, 2, 3, 4, 5]

O(2^n) — Экспоненциальная временная сложность

Когда введенный ввод увеличивается на единицу, количество выполняемых операций удваивается. В качестве очень хорошего примера можно привести последовательность Фибоначчи.

Пример:

Число Фибоначчи представляет собой математическую последовательность, в которой сумма двух предыдущих чисел становится третьим числом и так далее. Первые две цифры — 0 и 1, далее так: 1, 2, 3, 5, 8, 13…

Если заданное число для функции ниже является огромным, выходные данные достигнут очень высокого значения.

const recursiveFibonacci = (n) => {
  if (n < 2) {
    return n;
  }
  return recursiveFibonacci(n - 1) + recursiveFibonacci(n - 2);
};

recursiveFibonacci(6); 
// Output: 8

Вывод:

Обозначение Big O помогает разработчикам анализировать производительность алгоритмов. Это позволяет нам оптимизировать и создавать больше алгоритмов производительности.

Ресурсы:

Что такое нотация Big O — FreeCodeCamp

Большая О-нотация — ХанАкадемия

Контент:

Linkedin Github Twitter