Якщо ви хочете проаналізувати ці алгоритми, вам потрібно визначити // dostuff, оскільки це може дійсно змінити результат. Припустимо, що дозування вимагає постійної кількості операцій O (1).
Ось кілька прикладів із цим новим позначенням:
Для вашого першого прикладу лінійний обхід: це правильно!
O (N):
for (int i = 0; i < myArray.length; i++) {
myArray[i] += 1;
}
Чому вона лінійна (O (n))? Коли ми додаємо додаткові елементи до вводу (масиву), кількість операцій, що відбувається, збільшується пропорційно кількості доданих нами елементів.
Отже, якщо потрібна одна операція, щоб збільшити ціле число десь у пам'яті, ми можемо моделювати роботу, яку робить цикл, за допомогою f (x) = 5x = 5 додаткових операцій. Для 20 додаткових елементів робимо 20 додаткових операцій. Один прохід масиву має тенденцію до лінійності. Так само такі алгоритми, як сортування відра, які здатні використовувати структуру даних, щоб зробити сортування за один прохід масиву.
Ваш другий приклад також був би правильним і виглядає так:
O (N ^ 2):
for (int i = 0; i < myArray.length; i++) {
for (int j = 0; j < myArray.length; j++) {
myArray[i][j] += 1;
}
}
У цьому випадку для кожного додаткового елемента в першому масиві i, ми повинні обробити ВСЕ з j. Додавання 1 до i насправді додає (довжину j) до j. Таким чином, ви праві! Ця закономірність є O (n ^ 2), або в нашому прикладі це фактично O (i * j) (або n ^ 2, якщо i == j, що часто трапляється при матричних операціях або квадратній структурі даних.
Третій приклад - де все змінюється залежно від товару; Якщо код як написаний, а виконувати речі є постійною, це насправді лише O (n), оскільки у нас є 2 проходи масиву розміром n, а 2n зменшується до n. Петлі, що знаходяться поза однією стороною, не є ключовим фактором, який може створювати 2 ^ n код; ось приклад функції, яка дорівнює 2 ^ n:
var fibonacci = function (n) {
if (n == 1 || n == 2) {
return 1;
}
else {
return (fibonacci(n-2) + fibonacci(n-1));
}
}
Ця функція дорівнює 2 ^ n, оскільки кожен виклик функції виробляє ДВА додаткових виклику до функції (Фібоначчі). Щоразу, коли ми викликаємо функцію, кількість роботи, яку ми повинні виконати, подвоюється! Це дуже швидко росте, як відрізати голову від гідри і щоразу проростати два нові!
Для вашого останнього прикладу, якщо ви використовуєте такий сорт nlgn, як сортування злиття, ви маєте рацію, що цей код буде O (nlgn). Однак ви можете використовувати структуру даних для розробки більш швидких сортів у конкретних ситуаціях (наприклад, над відомим обмеженим діапазоном значень, таких як 1-100.) Ви вірно вважаєте, що переважає код вищого порядку; тому якщо сортування O (nlgn) знаходиться поруч з будь-якою операцією, яка займає менше, ніж O (nlgn) часу, загальна часова складність буде O (nlgn).
У JavaScript (як мінімум у Firefox) сортування за замовчуванням у Array.prototype.sort () дійсно є MergeSort, тому ви дивитесь на O (nlgn) для свого остаточного сценарію.