Hack Bulgaria
github.com/HackBulgaria
Обикновенно броим стъпките, които един алгоритъм прави, за да си свърши работата.
Логиката е, че алгоритъмът, който прави по-малко стъпки, за да приключи е по-бърз от този, който решава проблема с повече стъпки.
Моделът е по-сложен, но за простота, ще приемем че 1 стъпка на алгоритъма представлява 1 инструкция към процесора.
package com.hackbulgaria.datastructures;
public class Examples {
public static double average(int[] numbers) {
double sum = 0;
int i = 0;
int n = numbers.length;
while (i < n) {
sum = sum + numbers[i];
i = i + 1;
}
return sum / n;
}
public static void main(String[] args) {
int[] array = { 1, 2, 3, 4 };
System.out.println(String.format("Average: %.2f", average(array)));
}
}
package com.hackbulgaria.datastructures;
public class Examples {
public static boolean sumToZero(int[] numbers) {
boolean result = false;
int n = numbers.length;
for(int i = 0; i < n; i += 1) {
for(int j = 0; j < n; j += 1) {
if(numbers[i] + numbers[j] == 0) {
result = true;
break;
}
}
}
return result;
}
public static void main(String[] args) {
int[] array = { 2, 3, 4, -1, 1 };
System.out.println(String.format("To zero: %b",
sumToZero(array)));
}
}
vs.
За нас, те ще са "еднакви" откъм скорост.
Броенето на инструкции е трудно и тежко. Трябва ни "по-мърлезив" подход за по-груба оценка.
vs.
Освен ако c1 и c2 не са със стойности >= на n, няма да взимаме и тези константи предвид. Правим си живота по-лесен.
Ако имаме две функции, които при един и същи вход дават един и същи резултат
Може да "анализираме" коя от двете функции ще бъде по-ефективна.
Ще сравняваме на много високо ниво. Ще се интересуваме от класове от функции, вместо конкретни константи.
Всички функции от горния вид ще наричаме "линейни" и няма да се интересуваме от константите c1 и c2
Всички функции от горния вид ще са "квадратни" за нас и няма да се интересуваме от c1, c2, n и c3
public class Example {
public static boolean search(int element, int[] items) {
for (int item : items) {
if (item == element) {
return true;
}
}
return false;
}
public static void main(String[] args) {
int[] array = { 2, 3, 4, -1 };
int[] largeArray = new int[1000000];
largeArray[1000000 - 1] = 2;
System.out.println(search(2, array)); // 1 step
System.out.println(search(2, largeArray)); // 999999 steps
}
}
Може да приключим търсенето за 1 стъпка, но ние ще оценим алгоритъма все едно елементът е последен.
Това се наирача "линейно" търсене, защото прави едно пълно обхождане, за да намери даден елемент.
Когато гледаме за най-лошият вариант, има специална нотация за това. Нарина се "Big-Oh Notation"
Казваме, че сложността на нашето търсене е:
Ако алгоритъмът има O(n) сложност, това означава, че стъпките, които са му нужни, са пропорционални на дължината на входа.
package com.hackbulgaria.datastructures;
public class Examples {
public static boolean sumToZero(int[] numbers) {
boolean result = false;
int n = numbers.length;
for(int i = 0; i < n; i += 1) {
for(int j = 0; j < n; j += 1) {
if(numbers[i] + numbers[j] == 0) {
result = true;
break;
}
}
}
return result;
}
public static void main(String[] args) {
int[] array = { 1, 2, 3, 4, -1 };
System.out.println(String.format("To zero: %b",
sumToZero(array)));
}
}
Ще сравняваме нашите алгоритми използвайки "Big-Oh" нотацията.
By Hack Bulgaria