Рубрики
Без рубрики

Алгоритмы на простом английском: временная сложность и нотация Big-O

Алгоритми Михаила Олоруннисола в простом английском языке: Сложность времени и Big-O Уведомление о том, чтобы хороший разработчик у нас на уме. Они хотят дать своим пользователям больше этого, чтобы они могли делать все эти вещи, которыми они наслаждаются. Они делают это путем минимизации сложности времени. Прежде чем вы сможете понять сложность времени

Автор оригинала: FreeCodeCamp Community Member.

Михаилом Олоруннисола

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

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

Так что же алгоритм, в любом случае?

Проще говоря, алгоритм представляет собой серию содержащихся шагов, которые вы следуете, чтобы достичь некоторой цели, или для получения некоторый вывода. Давайте возьмем, например, рецепт вашего бабушки для выпечки торта. Подождите, это считается алгоритмом? Конечно, это делает!

function BakeCake(flavor, icing){
"
 1. Heat Oven to 350 F
 2. Mix flour, baking powder, salt
 3. Beat butter and sugar until fluffy
 4. Add eggs.
 5. Mix in flour, baking powder, salt
 6. Add milk and " + flavor + "
 7. Mix further
 8. Put in pan
 9. Bake for 30 minutes
10." + if(icing === true) return 'add icing' + "
10. Stuff your face
"
}

BakeCake('vanilla', true) => deliciousness

Алгоритмы полезны в нашем рассмотрении сложности времени, потому что они приходят во всех формах и размерах.

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

Таким образом, главный вопрос: как мы проаналируем, какие решения наиболее эффективны?

Математика к спасению! Анализ сложности времени в программировании является просто чрезвычайно упрощенный математический способ анализа того, как долго алгоритм с заданным количеством входов (N) примет, чтобы завершить его задачу. Обычно это определено, используя Обозначение Big-O Отказ

Что такое большая нотация, вы спрашиваете?

Если вы обещаете, что вы не сдадитесь и прекратите читать, я скажу вам.

Обозначение Big-o – это способ преобразования общих этапов алгоритма в алгебраические термины, затем исключая константы и коэффициенты более низкого порядка, которые не имеют большого влияния на общую сложность проблемы.

Математики, вероятно, немного будут съеживаться в предположении о моем «общем воздействии», но для разработчиков экономить время, легче упростить вещи таким образом:

Regular       Big-O

2             O(1)   --> It's just a constant number

2n + 10       O(n)   --> n has the largest effect

5n^2          O(n^2) --> n^2 has the largest effect

Короче говоря, все это пример говорит: мы смотрим только на фактор в нашем выражении, которое оказывает вероятно наибольшее влияние на значение, которое наше выражение вернется. (Это меняется, как постоянная, становится чрезвычайно большим, и N становится маленьким, но давайте не будем беспокоиться об этом на данный момент).

Ниже приведены некоторые общие временные сложности с простыми определениями. Не стесняйтесь проверить Википедия Однако, для более глубоких определений.

  • O (1) – постоянное время: Учитывая ввод размера n, это требуется только один шаг для алгоритма для выполнения задачи.
  • O (log n) – логарифмическое время: с учетом ввода размера n, количество шагов, необходимых для выполнения задачи, уменьшается в некоторых факторе с каждым шагом.
  • O (n) – линейное время: Учитывая ввод размера n , количество требуемых шагов напрямую связано (от 1 до 1)
  • O (n²) – квадратное время: Учитывая вход размера n, количество шагов, необходимых для выполнения задачи, является квадратным из N.
  • O (c ^ n) – экспоненциальное время: Учитывая ввод размера n, количество шагов, необходимых для выполнения задачи, является постоянным для N Power (довольно большое количество).

С этими знаниями в руках давайте посмотрим количество шагов, которые каждый из этих сложностей влечет за собой:

let n = 16;

O (1) = 1 step "(awesome!)"

O (log n) = 4 steps  "(awesome!)" -- assumed base 2

O (n) = 16 steps "(pretty good!)"

O(n^2) = 256 steps "(uhh..we can work with this?)"

O(2^n) = 65,536 steps "(...)"

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

Итак, как мы пойдем о анализе нашего кода с обозначением Big-O?

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

Мы будем использовать структуры данных ниже для наших примеров:

var friends = {
 'Mark' : true,
 'Amy' : true,
 'Carl' : false,
 'Ray' :  true,
'Laura' : false,
}
var sortedAges = [22, 24, 27, 29, 31]

O (1) – Постоянное время

Значение Посмотрите UPS, если вы знаете, что ключ (объекты) или индекс (массивы) всегда принимают один шаг, и, таким образом, постоянное время.

//If I know the persons name, I only have to take one step to check:

function isFriend(name){ //similar to knowing the index in an Array 
  return friends[name]; 
};

isFriend('Mark') // returns True and only took one step

function add(num1,num2){ // I have two numbers, takes one step to return the value
 return num1 + num2
}

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

Если вы знаете, какую сторону массива смотрели на предмет, вы экономите время, вырезая другую половину.

//You decrease the amount of work you have to do with each step

function thisOld(num, array){
  var midPoint = Math.floor( array.length /2 );
  if( array[midPoint] === num) return true;
  if( array[midPoint] < num ) --> only look at second half of the array
  if( array[midpoint] > num ) --> only look at first half of the array
  //recursively repeat until you arrive at your solution
  
}

thisOld(29, sortedAges) // returns true 

//Notes
 //There are a bunch of other checks that should go into this example for it to be truly functional, but not necessary for this explanation.
 //This solution works because our Array is sorted
 //Recursive solutions are often logarithmic
 //We'll get into recursion in another post!

На) — Линейное время

Вы должны посмотреть на каждый элемент в массиве или списке для выполнения задачи. Одинокий для петлей почти всегда линейные временем. Также методы массива, такие как Индекс также линейное время. Вы просто абстрагированы от процесса цикла.

//The number of steps you take is directly correlated to the your input size

function addAges(array){
  var sum = 0;
  for (let i=0 ; i < array.length; i++){  //has to go through each value
    sum += array[i]
  }
 return sum;
}

addAges(sortedAges) //133

O (n²) – Квадратное время

Вложенные для петлей Квадратичное время, потому что вы используете линейную работу в течение другой линейной операции (или).

//The number of steps you take is your input size squared

function addedAges(array){
  var addedAge = [];
    for (let i=0 ; i < array.length; i++){ //has to go through each value
      for(let j=i+1 ; j < array.length ; j++){ //and go through them again
        addedAge.push(array[i] + array[j]);
      }
    }
  return addedAge;
}

addedAges(sortedAges); //[ 46, 49, 51, 53, 51, 53, 55, 56, 58, 60 ]

//Notes
 //Nested for loops. If one for loop is linear time (n)
 //Then two nested for loops are (n * n) or (n^2) Quadratic!

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

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

//The number of steps it takes to accomplish a task is a constant to the n power

//Thought example
 //Trying to find every combination of letters for a password of length n

Вы должны выполнить анализ сложности времени в любое время, когда вы пишете код, который должен работать быстро.

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

Чтобы помочь вам с процессом решения проблем, вот несколько простых вопросов, которые нужно задать:

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

Опять же, большинство проблем вы столкнетесь с программистом – будь то алгоритмический или программный – будет иметь десятки, если не сотни способов ее решения. Они могут варьироваться в том, как они решают проблему, но все еще решают эту проблему.

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

Учитывая это, сложно сказать, что есть один «правильный» или «лучший» ответ на эти проблемы. Но можно сказать, что есть «лучше» или «хуже» ответы на данную проблему.

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

Способность описать лучшее решение обычно пружины от некоторого видимости анализа сложности времени.

Короче говоря, если вы собираетесь решить проблему, решайте это хорошо. И используйте немного Big-O, чтобы помочь вам выяснить, как.

Вот окончательный Recap:

  • O (1) – Постоянное время: это требуется только один шаг для алгоритма для достижения задачи.
  • O (log n) – Логарифмическое время: Количество шагов, необходимых для выполнения задачи, уменьшается на каждом шаге.
  • O (N) – Линейное время: количество требуемых шагов напрямую связано (от 1 до 1).
  • O (n²) – Квадратное время: Количество шагов, которые требуется для выполнения задачи, является квадрат.
  • O (C ^ n) – Экспоненциальный: количество шагов, необходимых для выполнения задачи, является постоянным для N Power (довольно большое количество).

И вот некоторые полезные ресурсы, чтобы узнать больше:

  • Википедия
  • Большой О. Чит лист является отличным ресурсом с общими алгоритмическими временными слоями и графическим представлением. Проверьте это!

Оригинал: “https://www.freecodecamp.org/news/time-is-complex-but-priceless-f0abd015063c/”