background top icon
background center wave icon
background filled rhombus icon
background two lines icon
background stroke rhombus icon

Скачать "Курс · Алгоритмы и структуры данных # ч.2 # Временная сложность и Анализ алгоритмов"

input logo icon
Обложка аудиозаписи
Подождите немного, мы готовим ссылки для удобного просмотра видео без рекламы и его скачивания.
console placeholder icon
Оглавление
|

Оглавление

0:00
Приветственное слово
0:37
Введение в анализ алгоритмов
16:13
Построение графика роста времени выполнения
22:28
Аппроксимация и порядок роста
29:47
Порядок роста / Временная сложность / Нотация О большое
Теги видео
|

Теги видео

c#
c# курс
engineerspock
алгоритмы
алгоритмы и структуры данных
алгоритмы на c#
анализ алгоритмов
аппроксимация
асимптотический анализ алгоритмов
временная сложность алгоритма
инженер спок
курс по алгоритмам
курс по структурам данных
нотация о большое
порядок роста функции
программирование
структуры данных
структуры данных в c#
структуры данных и алгоритмы
что такое алгоритм
что такое структура данных
it
айти
ityoutubersru
программист
разработка
ityoutubers
python
питон
ооп
Субтитры
|

Субтитры

subtitles menu arrow
  • enАнглийский
Скачать
00:00:00
бинарный Салют друзья на связи
00:00:02
инженерспок Сегодня выходит вторая часть
00:00:05
курса по алгоритмам и структурам данных
00:00:07
с примерами на сишарпе в этой серии вы
00:00:11
узнаете Что такое временная сложность а
00:00:14
проксимация порядок роста и разберете
00:00:16
пример с прогнозированием времени работы
00:00:19
алгоритма напомню что если вы хотите
00:00:22
приобрести полную версию курса то
00:00:24
переходите по ссылке в описании поехали
00:00:38
разрабатывая алгоритм для решения
00:00:40
конкретной проблемы вычислительной мы
00:00:42
задаем следующие вопросы Сколько времени
00:00:45
потребует Наш алгоритм Для решения
00:00:47
проблемы и Сколько памяти потребует наш
00:00:51
алгоритм Для решения проблемы и нам
00:00:53
нужно понимать Каким путем приходить к
00:00:57
ответам на эти вопросы Иначе мы не
00:00:59
сможем строить эффективные алгоритмы
00:01:01
которые смогут решать вычислительные
00:01:04
проблемы за приемлемое количество
00:01:06
времени с приемлемым потреблением памяти
00:01:08
к сожалению никакой Серебряной пули или
00:01:12
простого ответа который я мог бы вам
00:01:14
дать за одну минуту таким образом что вы
00:01:16
смогли бы легко и Непринужденно
00:01:18
оценивать эффективность любого алгоритма
00:01:20
такой пули или такого простого ответа их
00:01:23
просто нет Мне хотелось бы сделать этот
00:01:25
курс практически Так что я не буду
00:01:27
погружаться больно глубоко в теорию
00:01:30
экспериментов погружаться в какие-то
00:01:32
философские проблемы экспериментальных
00:01:34
наблюдений верифицируемости и прочее
00:01:37
вместо Давайте попробуем на практике
00:01:39
решить проблему Вот задачка проблема
00:01:43
скажем что нам нужно пройти по набору
00:01:46
целых чисел некий набор входных до целых
00:01:50
чисел у нас есть и нам нужно найти все
00:01:52
тройки чисел Ну то есть триплеты сумма
00:01:54
которых равна нулю Окей Похоже что у нас
00:01:57
есть краткое описание вычислительной
00:01:59
проблемы я переключусь пожалуй Visual
00:02:01
Studio и попробую реализовать простой
00:02:04
брут Force алгоритм который тупо
00:02:06
итерирует по всем триплетам и находит
00:02:09
такие суммы перед тем как приступить
00:02:11
непосредственно к реализации алгоритма я
00:02:14
хочу вам показать что вот я прикрепил
00:02:15
здесь к проекту несколько файлов которые
00:02:19
я честно говоря взял из одной известной
00:02:22
книжки по алгоритмам которая написана
00:02:24
Робертом седжиком открою например файл
00:02:27
который называется One kings.txt и вы
00:02:30
можете видеть что этот файл содержит
00:02:32
одну тысячу целых чисел и также у нас
00:02:36
имеются файлы который называется
00:02:38
tookings forkings at Kings и sixtenkins
00:02:42
который соответственно содержит 2000
00:02:44
чисел 4000 чисел 8000 чиселлы 16 чисел
00:02:47
для начала Давайте реализуем метод для
00:02:50
чтения целых чисел статический метод Я
00:02:54
создам для этого класс Это у нас будет
00:02:57
публичный класс я его назову in и я
00:03:00
определил статический метод который
00:03:03
будет возвращать Ай номера был целых
00:03:07
чисел и номер был целых чисел импортирую
00:03:10
Тип и метод будет называться read ins и
00:03:15
этот метод будет получать в качестве
00:03:16
аргумента путь к файлу откроем этот файл
00:03:20
через using Используя метод Open Text
00:03:25
вызовем его на классе файл он принимает
00:03:28
собственно путь к файлу и прочитаем файл
00:03:32
в цикле уайл будем читать файл
00:03:35
посредством вызова метода Redline до тех
00:03:38
пор пока не будет возвращен на и я здесь
00:03:42
использую конструкцию eld Return для
00:03:45
ленивого вычисления Но вообще говоря на
00:03:50
Верхнем уровне Мы скорее всего будем
00:03:51
вызывать торрей для того чтобы
00:03:54
материализовать результаты чтения целых
00:03:57
чисел из файла Так что мы в общем-то не
00:03:59
обязаны здесь возвращать айнумера было
00:04:02
используя eld Return мы могли бы просто
00:04:05
здесь вернуть на самом деле массив
00:04:07
Хорошо я
00:04:09
перемещу этот тип в свой отдельный файл
00:04:13
и вернусь обратно Да в общем Я
00:04:17
использовал конструкцию которая
00:04:19
позволяет
00:04:21
читать файл лениво
00:04:23
То есть если вдруг клиентская сторона не
00:04:26
заинтересована в том чтобы читать весь
00:04:28
файл она этого делать и не будет как я
00:04:31
уже сказал не уверен что эту фишку прям
00:04:33
уж так обязательно здесь использовать в
00:04:35
курсе но я так чисто на всякий случай
00:04:38
Так запрограммировал на самом деле в
00:04:41
большинстве случаев скорее всего мы
00:04:44
будем использовать жадные Линк операторы
00:04:46
наверху Да с клиентской стороны которая
00:04:49
будет пользоваться классом in такие
00:04:51
жадные операторы как то э Рей или Турист
00:04:54
которые будут просто форсировать полное
00:04:58
чтение файла хорошо Теперь давайте
00:05:00
реализуем алгоритм я буду держать
00:05:03
алгоритмы и структуры данных В отдельной
00:05:06
библиотеке классов Так что я сначала
00:05:08
создам проект это собственно будет
00:05:15
Да это страх либо Окей хорошо Так что
00:05:20
давайте создадим класс Я назову его три
00:05:24
сам и я реализую метод который будет
00:05:27
решать наши вычислительную проблему он
00:05:30
возвращает int И назову я его каунт и он
00:05:34
принимает набор входных данных это у нас
00:05:37
массив винтов назовем его и с целью
00:05:41
улучшения читабельности Для начала я
00:05:44
присвоил размер массива в переменную с
00:05:48
каким-нибудь коротким именем Пусть эта
00:05:50
переменную мы назовем N собственно и
00:05:54
присваиваю значение свойства Lands и
00:05:57
поскольку нам нужно посчитать количество
00:06:00
триплетов сумма которых равна нулю нам
00:06:04
нужно объявить некую аккумулирующую
00:06:07
переменную некий каунтер счетчик
00:06:09
собственно я его и назову каунтер и
00:06:12
присваиваем ему 0 отлично каков будет
00:06:16
наиболее простой алгоритм который
00:06:18
позволит нам решить нашу вычислительную
00:06:20
проблему я возьму несколько чисел и
00:06:23
Запишу их тут один три минус 2 1 -3 0
00:06:30
Для того чтобы проверить все три плиты
00:06:33
вот в таком случае
00:06:35
мне нужно сделать следующее взять первый
00:06:38
триплет это у нас 13 -2
00:06:41
поскольку мы здесь работаем с триплетами
00:06:44
Нам нужно три итератора Пусть это будут
00:06:47
Ай Джей и к вот предположим у нас первый
00:06:50
шаг на Первом шагу Ай у нас равно
00:06:52
единице J равна тройке а кей равно минус
00:06:55
2
00:06:56
Теперь будем инкрементировать кей до тех
00:06:58
пор пока кей не дойдет до конца набора
00:07:01
то есть мы таким образом получим такие
00:07:05
триплеты 1 3 1 3 - 3 1 3 0 и 132 затем
00:07:12
мы инкрементируем Джей на единичку и
00:07:17
возвращаем кей в исходное состояние но
00:07:20
только не совсем исходное оно зависит от
00:07:22
Джей то есть Кей Он вначале каждого
00:07:26
цикла будет указывать на элемент
00:07:29
следующий за элементом находящимся по
00:07:31
индексу J Так что следующим трепетом
00:07:34
будет один минус 2 1 И теперь мы снова
00:07:38
будем экспериментировать кей до тех пор
00:07:39
пока не дойдем до конца
00:07:41
и вот действовать Таким образом мы
00:07:43
проверим абсолютно все три плиты все
00:07:46
возможные триплеты без каких-либо
00:07:48
сомнений Давайте реализуем этот
00:07:51
невероятно простой алгоритм для этого
00:07:54
запустим цикл for I у нас будет меньше N
00:07:58
а J должен быть всегда впереди I Так что
00:08:04
Джей у нас будет равен I плюс 1 также
00:08:08
будет идти до n и Key должен быть у нас
00:08:12
всегда впереди Джей здесь у нас будет
00:08:15
еще один внутренний Ford цикл кей будет
00:08:17
начинаться с J + 1 и будет идти до n и
00:08:21
если айты плюс
00:08:26
а КТ равно 0 то есть сумма три полтора
00:08:31
на 0 мы инкрементируем контур то есть мы
00:08:34
нашли триплет
00:08:35
в конце концов возвращаем собственно
00:08:38
а теперь Давайте попробуем ответить на
00:08:40
вопрос Сколько времени потребуется для
00:08:43
того чтобы этот алгоритм отработал на
00:08:46
входном наборе который содержит одну
00:08:49
тысячу целых чисел 4000 целых чисел и
00:08:52
8000 целых чисел что ж Ну можно было бы
00:08:56
для этого использовать таймер правильно
00:08:58
для того чтобы Засечь логично Давайте
00:09:01
померяем время для решения
00:09:03
вычислительной задачи размером в одну
00:09:07
тысячу целых чисел для этого я буду
00:09:10
использовать класс который называется
00:09:11
стоп вотч он представляет собой
00:09:15
высокоточный таймер в дотете Для начала
00:09:18
я прочитаю все целые числа из файла один
00:09:24
kinds.txt кстати говоря все эти файлы
00:09:26
должны быть скопированы в выходную
00:09:28
директорию нашего проекта Да я думал от
00:09:31
копии поменяю на копии февр чтобы у нас
00:09:35
был доступ к этим файлам чтобы они
00:09:37
копировались мы их легко читали вот мы
00:09:39
их читаем и применяем Toe Ray то есть а
00:09:43
и номер был конвертируем в массив затем
00:09:46
объявляем наш таймер
00:09:47
newstopwatch запускаю методом Start и
00:09:53
собственно считаем наши триплеты вызовом
00:09:57
метода Count который мы только что
00:10:00
реализовали сам аккаунт Передаем список
00:10:03
целых чисел внутрь метода Count почему у
00:10:07
меня нет доступа к 3 сам а я должен за
00:10:12
референсить библиотеку Да массив И после
00:10:17
этого мы должны остановить наш таймер
00:10:19
для того чтобы оценить время
00:10:22
затраченное на подсчет триплетов Ну и
00:10:26
здесь что-нибудь заблокируем скажем
00:10:27
количество
00:10:29
зеро сам триплетов равно триплет Скаут
00:10:33
Ну передадим Здесь три плюс Скаут просто
00:10:35
выведем на были просто три плюс Да и
00:10:38
залагируем количество времени
00:10:39
затраченное для этого нам нужно
00:10:41
воспользоваться свойством лэпст и с
00:10:45
форматируем его через чтобы там просто у
00:10:48
нас удобный вывод был так если я запущу
00:10:51
эту программу в режиме релиз чтобы
00:10:56
программа побыстрее работала Давайте
00:10:58
попробуем посмотрим на результат так
00:11:01
можете видеть что наш алгоритм решила
00:11:05
эту проблему примерно за 300 миллисекунд
00:11:08
найдя 73 пледов сумма которых равна нулю
00:11:11
использование стоп вотч напрямую не
00:11:15
всегда является таким уж Хорошим
00:11:17
способом для того чтобы замерить
00:11:18
производительность но конкретно в нашем
00:11:22
случае этого будет достаточно для нашей
00:11:24
дискуссии
00:11:26
вообще говоря
00:11:28
замеры производительности зачастую
00:11:30
называются бенчмаркинг и это отдельный
00:11:33
большой очень интересный раздел так
00:11:37
сказать знаний которые надо отдельно
00:11:39
изучать он полон подводных камней но это
00:11:42
уже выходит за рамки нашего курса
00:11:44
Поэтому Давайте вернемся к нашей
00:11:46
основной дискуссии так вот вы видите что
00:11:48
нашему алгоритму потребовалось примерно
00:11:49
300 миллисекунд для того чтобы решить
00:11:52
вычислительную задачу размером в одну
00:11:53
тысячу целых чисел а Можете ли вы теперь
00:11:56
ответить на вопрос сколько же нашему
00:11:58
алгоритму потребуется для того чтобы
00:11:59
решить вычислительную задачу размером в
00:12:02
4000 чисел Можем ли мы просто полученные
00:12:06
наши результат 300 миллисекунд помножить
00:12:08
на 4 для того чтобы примерно для того
00:12:12
чтобы примерно предсказать время
00:12:14
выполнения нашего алгоритма для размера
00:12:17
4000 целых чисел Но ведь 4000 в четыре
00:12:21
раза больше чем одна тысяча правильно
00:12:23
Ну хорошо не буду вас мучить влияние
00:12:27
жесткий профессор с бородой из см АйТи и
00:12:32
если вы опытный разработчик то конечно
00:12:35
вы знаете о понятии вычислительной
00:12:38
сложности и в таком случае Конечно вы
00:12:41
уже догадались что просто так
00:12:43
перемножить то что мы получили наш
00:12:46
результат на 4 для того чтобы
00:12:48
предсказать
00:12:49
вычислительное время для проблемы
00:12:51
размером в 4000 целых чисел мы не можем
00:12:54
Вот это вычислительное время которое
00:12:55
затрачивается до алгорит Ну Сколько
00:12:58
занимает алгоритм мы на английском также
00:13:00
называем Running Time для того чтобы на
00:13:03
практике продемонстрировать то что
00:13:04
перемножение на 4 не работает я просто
00:13:07
запущу нашу программу скормив ей файл в
00:13:10
4000 целых чисел здесь поменяем 1 на 4 и
00:13:15
запустим наш алгоритм залогирую первый
00:13:18
результат у нас был 300 миллисекунд
00:13:25
Running Time нашего алгоритма в случае
00:13:30
четырех тысяч чисел во входной
00:13:33
последовательности равен почти 14 секунд
00:13:36
То есть наш алгоритм отрабатывал почти
00:13:38
14 секунд для того чтобы найти все Zero
00:13:41
Sam 3 плиты нашел Их 4000 39 штук и надо
00:13:45
сказать что этот результат явно
00:13:47
очень-очень далек от того результата
00:13:51
который мы получили просто перемножив
00:13:53
300 миллисекунд на 4 А теперь давайте
00:13:56
посмотрим на результат запуска нашего
00:13:59
алгоритма на входной последовательности
00:14:00
размером 8000 целых чисел так
00:14:04
заблокируем 14 секунд для 4000 чисел и
00:14:09
что у нас для 8000 запустим
00:14:19
и результат равен примерно
00:14:23
одна минута 36 секунд если округлить то
00:14:28
получается даже одна минута 37 секунд Вы
00:14:32
можете заметить что потребление времени
00:14:34
Да этот самый Running Time растет
00:14:37
нелинейно не линейно мы удваиваем размер
00:14:41
входной последовательности а Running
00:14:43
Time не удваивается растет гораздо
00:14:46
быстрее так что же нам делать для того
00:14:49
чтобы предугадать Сколько времени займет
00:14:53
процессинг 16 тысяч целых чисел или 128
00:14:57
тысяч целых чисел я сомневаюсь что вы
00:15:00
будете заинтересованы в запуске
00:15:03
программы со входной последовательностью
00:15:06
128 тысяч целых чисел на практике чтобы
00:15:08
результат никогда не дождетесь Ну или
00:15:11
будете ждать его слишком долго Поэтому
00:15:13
нам нужны какие-то теоретические модели
00:15:15
теоретические понятия для того чтобы
00:15:16
такие вещи вычислять как-то а более того
00:15:19
любая проблема в оценках алгоритмов
00:15:21
заключается в том что Ну вот например
00:15:23
если вы запустите этот код на своем
00:15:24
компьютере то скорее всего вы получите
00:15:27
другие результаты не такие как на моем
00:15:29
компьютере который работает на Intel
00:15:34
Core i7 3630qm достаточно неплохой
00:15:38
мобильный процессор конечно далек от
00:15:41
каких-то там топовых но вполне неплохой
00:15:43
тем не менее вы получите другие
00:15:45
результаты конечно рост у вас будет
00:15:48
времени затрачиваемого на решение
00:15:51
вычислительных проблем точно такой же но
00:15:54
фактически Результаты будут отличаться и
00:15:57
таким образом вопрос который мы себе
00:15:59
задаем когда оцениваем алгоритм должен
00:16:01
звучать так как долго будет работать мой
00:16:04
алгоритм будучи функцией от размеров
00:16:08
входной последовательности Давайте
00:16:10
немножко займемся математикой в
00:16:12
следующей лекции чтобы вывести функцию
00:16:15
описывающую рост времени выполнения
00:16:18
зависящего от размера ввода необходимо
00:16:20
построить график очень часто нам
00:16:24
приходится отображать какие-то крупные
00:16:27
числа на графике и в таком случае мы
00:16:31
прибегаем к построению так называемых
00:16:33
Log Lock графиков логарифмических
00:16:35
например в данном случае нам нужно на
00:16:38
графике будет отобразить 96 секунд
00:16:40
потому что у нас там была одна минута 36
00:16:42
секунд в качестве одного из результатов
00:16:44
выполнения алгоритма для этого мы будем
00:16:48
использовать логарифмический график
00:16:50
Давайте построим такой график опуская
00:16:53
всякие теоретические рассуждения для
00:16:56
того чтобы построить логарифмический
00:16:57
график нам нужно выбрать основание
00:16:59
логарифма обычно используются основания
00:17:02
2 или 10 в нашем случае достаточно в
00:17:05
качестве основания использовать
00:17:06
основание 2 для того чтобы построить
00:17:11
логарифмический график основанный на
00:17:13
экспериментальных данных которые мы
00:17:15
получили запуская нашу программу на
00:17:18
вычислительных проблемах разной разного
00:17:21
размера нам нужно Отложить на оси X
00:17:24
размеры проблем то есть размеров
00:17:27
последовательности входных данных и
00:17:30
время затраченное на решение проблемы по
00:17:33
оси Y используя наши экспериментальные
00:17:36
данные Мы можем поставить три точки на
00:17:39
графике и соединить их линией для того
00:17:44
чтобы понять для того чтобы понять как
00:17:47
растет время выполнения нам нужно
00:17:49
вычислить наклон линии которую мы
00:17:52
нарисовали для того чтобы вычислить
00:17:54
наклон линии на логарифмическом графике
00:17:58
нам нужно взять две точки Давайте скажем
00:18:02
что мы возьмем
00:18:03
Ну собственно например вот мы возьмем
00:18:05
значит две точки первая точка У нас у
00:18:09
нее будут координаты X1 равная 8y 1
00:18:12
равен 96 и вторая точка X2 значит у нее
00:18:18
будет равен 4 y2 равен 14 Ну где 8 и 4
00:18:22
это у нас размеры проблем а 96 и 14 это
00:18:26
количество затраченных секунд на решение
00:18:27
проблемы Теперь мы можем использовать
00:18:29
простую формулу для того чтобы вычислить
00:18:32
наклон Для этого нам нужно разделить y1
00:18:35
на y2 и взять логарифм от результата по
00:18:39
основанию 2 и результат поделить на
00:18:42
логарифм по основанию 2 от результата
00:18:46
деления X1 на X2 Ну и в результате всех
00:18:50
этих вычислений мы получим что
00:18:52
наклон линии примерно равен 3
00:18:56
Таким образом мы можем составить
00:18:58
следующее уравнение логарифм от функции
00:19:02
teathen это у нас функция которая будет
00:19:06
описывать рост времени выполнения равно
00:19:10
3 умноженное на логарифм от N плюс
00:19:14
логарифм от А где А это некоторая
00:19:18
Константа мы вводим логарифм от а потому
00:19:21
что на самом деле рост времени
00:19:23
выполнения зависит от множества мелких
00:19:26
факторов которые в большинстве случаев
00:19:29
не релевантные но тем не менее в
00:19:32
уравнение мы можем их в общем включить
00:19:34
мы можем использовать свойства
00:19:37
логарифмических степеней и возвести N в
00:19:40
степень тройки и используя свойства
00:19:42
перемножения логарифмов объединить
00:19:45
логарифмы с правой стороны и в
00:19:48
результате мы получим следующее
00:19:50
уравнение логарифм tn равен логарифм А
00:19:54
умноженное на N в третьей
00:19:56
После этого мы можем просто разделить
00:19:59
обе стороны уравнения на логарифм и
00:20:03
прийти к следующему выражению teat N
00:20:06
равно an в третьей степени Теперь
00:20:10
давайте вычислим а для этого мы можем
00:20:13
использовать наши экспериментальные
00:20:15
данные N это у нас как вы понимаете
00:20:17
размер задачи Так что т от 8000 равен 96
00:20:22
потому что у нас от 8000 время
00:20:26
выполнения заняло 96 секунд равно А
00:20:29
умноженное на 8000 в кубе В результате
00:20:32
вычислений мы получаем 18,7 умноженное
00:20:36
на 10 в минус 11 степени мы вычислили а
00:20:39
и теперь если мы подставляем в то
00:20:41
выражение которое у нас есть выше ты от
00:20:44
N равно А умноженная куб получаем tn
00:20:47
равно 18,7 умноженное на 10 в минус 11
00:20:50
степени умноженное на N в кубе и таким
00:20:53
образом Имея это описание этой функции
00:20:56
функции описывающие рост времени
00:21:00
исполнения алгоритма А мы можем теперь
00:21:03
предсказывать время исполнения Для
00:21:06
различных размеров задачи Ну например мы
00:21:10
можем подставить 16 тысяч до и тогда
00:21:13
просто вычислим что предварительно Ну
00:21:17
конкретно вот на моей машине
00:21:18
предварительно мы можем предположить что
00:21:20
время исполнения для задачи в 16 тысяч
00:21:22
чисел будет равно примерно 766 секунд То
00:21:27
есть чуть больше 10 минут Ну и
00:21:29
нормальное отклонение от числа которое
00:21:32
мы получили примерно равно 2-3 процентам
00:21:35
отлично И все что нам осталось сделать
00:21:37
это проверить корректность нашего
00:21:40
вычисления Давайте попробуем Так что я
00:21:43
передам 16
00:21:46
и запущу программу
00:21:59
и вы можете видеть что результат который
00:22:03
мы получили он довольно близок к тому
00:22:05
что мы предсказывали если вы Спросите
00:22:08
себя Возможно ли улучшить временную
00:22:11
сложность алгоритма Для решения проблемы
00:22:14
зиры сам триплетов я Вам отвечу Да это
00:22:17
возможно и я вам продемонстрирую
00:22:20
возможное улучшение чуть позже а пока
00:22:23
Давайте в следующей лекции поговорим об
00:22:25
еще одной важной теме об аппроксимациях
00:22:29
определяя рост времени исполнения мы не
00:22:32
делали это с высокой точностью И вообще
00:22:35
говоря я объяснял Почему все дело в том
00:22:37
что в 99 процентах случаев нам
00:22:40
неинтересны не значимые члены полинома
00:22:43
Так что мы их просто отрезаем Хотя
00:22:45
конечно в принципе мы можем строить
00:22:48
Более точные математические модели
00:22:50
описывающие функцию роста времени
00:22:53
исполнения Достаточно давно
00:22:55
Дональд кнут постулировал Что для того
00:22:59
чтобы по свою точную математическую
00:23:00
модель описывающую время выполнения
00:23:02
любой программы необходимо принять во
00:23:05
внимание два основных фактора первый
00:23:07
фактор это стоимость выполнения каждой
00:23:10
инструкции в программе и второй фактор
00:23:13
это частота выполнения каждой инструкции
00:23:15
в программе первый фактор очень сильно
00:23:18
зависит от всяких внешних вещей которые
00:23:20
влияют на исполнение программы такие как
00:23:23
операционная система среда исполнения
00:23:26
например Dot netcalar javaran Time и так
00:23:30
далее железо которое было использовано
00:23:33
на котором запускался алгоритм и другие
00:23:36
еще менее значимые под факторы если мы
00:23:40
можем точно оценить оба фактора тогда
00:23:44
для того чтобы вычислить время
00:23:46
исполнения нам нужно там все перемножить
00:23:49
и сложить Однако первый Фактор в
00:23:51
настоящее время то есть фактор стоимости
00:23:53
выполнения каждой инструкции в 99
00:23:56
процентах случаев в настоящее время для
00:23:58
нас вообще не абсолютно По той простой
00:24:02
причине что
00:24:03
современные компьютеры
00:24:05
работают невообразимо быстро как
00:24:08
говорится на английском Lightning Fest
00:24:10
как молния Да что по сути означает что
00:24:13
время исполнения отдельных инструкций
00:24:16
Оно просто невероятно высокое таким
00:24:20
образом этот фактор он имеет крайне
00:24:23
лимитированное влияние на конечную
00:24:25
оценку
00:24:26
времени исполнения алгоритма особенно
00:24:30
если мы говорим о проблемах очень
00:24:33
большого размера Ну действительно если
00:24:36
запуск алгоритма на Core i5 у нас
00:24:40
занимает 100 лет 100 лет для решения
00:24:43
задачи то нам переход на Core i7 который
00:24:46
допустим в четыре раза быстрее чем Core
00:24:48
i5 мало чем поможет потому что в
00:24:51
результате наш алгоритм будет работать
00:24:52
не столь Это 25 лет что по-прежнему
00:24:54
будет ну слишком долго таким образом
00:24:57
настоя
00:24:59
Челлендж для нас
00:25:01
настоящее испытания настоящая задача это
00:25:04
определение чистоты исполнения
00:25:07
инструкций и попытка их сократить Как
00:25:11
можно сильнее да то есть как можно
00:25:14
сильнее сократить количество выполняемых
00:25:16
инструкций вот в предыдущих лекциях Мы
00:25:19
пытались решить проблему триплетов
00:25:21
нулевыми суммами И для этого мы
00:25:24
запускали тройной вложенный цикл то есть
00:25:26
for вложенный for вложенный в for и в
00:25:29
результате получали временную сложность
00:25:31
описываемую кубической функцией то есть
00:25:34
N Cube примерно N куб хотя мы могли бы
00:25:38
конечно дать и Более точные оценки Ну
00:25:41
действительно как много итераций дает
00:25:44
первый второй и третий циклы вместе Ну
00:25:49
другими словами как много и в statement
00:25:52
of будет в результате исполнено сколько
00:25:55
раз и в statement и в блок будет запущен
00:25:58
для того чтобы оценить это число нам
00:26:00
потребуются некоторое понимание
00:26:01
статистики Если вкратце то мы должны
00:26:04
использовать формулу подсчета количество
00:26:06
варианта выбора различных чисел из
00:26:10
входного массива и такая оценка может
00:26:13
быть представлена следующим полиномом N
00:26:15
на N -1 на N - 2 деленное на 6
00:26:18
количество инкрементаций внутри и в
00:26:20
блока зависит от размера ввода и
00:26:23
единственное что мы можем сделать для
00:26:26
грубой оценки это использовать мощь
00:26:28
статистики опять вычисляя среднее
00:26:32
количество триплетов сумма которых равна
00:26:34
нулю на скажем каждую тысячу триплетов и
00:26:38
используя эти результаты предугадать
00:26:40
количество инкрементации для проблем
00:26:43
большего размера Мы правда не будем это
00:26:46
здесь делать поскольку это нерелевантно
00:26:48
с точки зрения обучающего процесса в
00:26:51
данном курсе Мы просто раскроем круглые
00:26:54
скобки в пленуме и придем к следующему
00:26:57
выражению N куб на 6 минус n квадрат
00:27:01
деленное на 2 + N / 3 А как вы можете
00:27:04
видеть анализ чистоты исполнения
00:27:07
программных конструкций может приводить
00:27:10
к довольно сложному вычислениям и
00:27:12
выражением и именно по этой причине мы
00:27:15
склонны использовать так называемую
00:27:18
Тильда проксимацию для того чтобы
00:27:20
отрезать не значимые члены Ну
00:27:24
действительно если N равняется 1000 то N
00:27:27
куб дает нам число которое больше 166
00:27:32
миллионов В то время как n квадрат
00:27:34
делённая на два плюс N деленное на 3 при
00:27:38
постановке тысячи вместо N будет давать
00:27:42
нам число меньше чем 500 тысяч 166
00:27:45
миллионов гораздо гораздо больше чем 500
00:27:49
тысяч и учитывая это мы при анализе
00:27:53
можем просто отрезать эти не значимые
00:27:57
члены просто в целях упрощения срезание
00:28:00
членов низшего порядка называется Тильда
00:28:03
апраксимацией и мы ее записываем
00:28:05
используя Тильда нотацию вот некоторые
00:28:08
примеры применения Тильда аппроксимации
00:28:10
первый пример показывает аппроксимацию
00:28:13
функции которую мы уже видели члены
00:28:16
высшего порядка здесь это Инкуб второй
00:28:19
пример демонстрирует функцию такую же
00:28:22
как в первом случае только там
00:28:23
изначально срезан куб то есть функция
00:28:25
квадрат деленное на два плюс n/3 в этом
00:28:28
случае n квадрат будет гораздо более
00:28:31
значимым членом чем деленное на 3 и
00:28:34
конечно же определяя порядок роста мы
00:28:37
можем отрезать все константы Даже те
00:28:39
которые оказывают влияние на члены
00:28:41
самого высшего порядка в первом случае
00:28:43
мы например отрезали деление на 6 н Куба
00:28:46
а во втором случае отрезали деление на
00:28:49
два третий пример показывает что n
00:28:51
квадрат гораздо больше Log N более того
00:28:55
даже просто N гораздо более значимо
00:28:59
диалог N Как показывает четвертый пример
00:29:01
И последние два примера демонстрируют то
00:29:04
что мы можем отрезать любые константы
00:29:06
когда мы определяем порядок роста говоря
00:29:10
порядок роста Я конечно же имею ввиду
00:29:12
порядок роста времени исполнения
00:29:14
алгоритма даже достаточно большие
00:29:17
константы Ну конечно в пределах
00:29:20
разумного не имеют действительно
00:29:22
значимого влияния на порядок роста
00:29:25
времени исполнения Так что в 99
00:29:27
процентах случаев при оценке роста
00:29:31
времени исполнения мы можем их просто
00:29:33
отрезать отлично следующие лекции
00:29:37
Давайте поговорим как раз об этих самых
00:29:39
порядках роста Что за такие порядки
00:29:41
роста и что такое О большое или как
00:29:44
говорят на английском Big On atation
00:29:47
Итак в данной лекции Я хочу немного
00:29:50
порассуждать о часто встречаемых
00:29:53
функциях описывающих рост времени
00:29:56
исполнения и первая такая функция
00:29:59
экспоненциальная описывающая понятное
00:30:01
дело экспоненциальный рост например
00:30:03
временная сложность вскрытия пароля
00:30:06
через тупорылый подбор просто простой
00:30:10
перебор Да brute Force с предположением
00:30:13
что пароль у нас длиной N будет
00:30:16
описываться функцией 10 в степени N и
00:30:19
конечно же почти нет никакого смысла в
00:30:22
запуске таких алгоритмов временная
00:30:25
сложность которых экспоненциально для
00:30:27
решения достаточно больших проблем
00:30:29
достаточно больших проблем такой
00:30:30
алгоритм запускать бессмысленно если
00:30:32
пароль состоит из трех символов куда не
00:30:34
шло Но если пароль серьезный то
00:30:36
подобрать его будет нереально просто
00:30:39
человеческой жизни не хватит для того
00:30:42
чтобы дождаться окончания работы этого
00:30:44
алгоритма тот кто его запустил умрет
00:30:46
гораздо 3 к сожалению в реальном мире
00:30:49
действительно существуют реальные
00:30:51
проблемы для которых Судя по всему
00:30:54
существуют алгоритмы
00:30:56
показывающие временную сложность не
00:30:59
лучше чем экспоненциальную то есть есть
00:31:01
проблемы которые мы можем решать только
00:31:04
с помощью алгоритмов показывающих
00:31:06
временную сложность
00:31:08
экспоненциальную и мы ничего В связи с
00:31:11
этим не можем сделать в тех случаях
00:31:13
когда алгоритм имеет
00:31:15
экспоненциальную временную сложность и
00:31:17
мы рассуждаем о решении задач
00:31:20
гигантского размера то такие алгоритмы
00:31:23
мы запускаем на суперкомпьютерах для
00:31:25
того чтобы хоть как-то в какой-то
00:31:27
степени ускорить исполнение алгоритма Ну
00:31:31
чтобы иметь возможность дождаться
00:31:33
все-таки какого-то результата вы уже
00:31:36
видели пример алгоритма со временной
00:31:39
сложностью кубической это я говорю о том
00:31:42
алгоритме который мы написали Для
00:31:43
решения проблемы нахождения Zero
00:31:46
триплетов такие алгоритмы обычно имеют
00:31:50
тройное вложенный цикл Если вы видите
00:31:53
тройной вложенный цикл то как правило Ну
00:31:55
в алгоритме видите то как правило значит
00:31:58
временная сложность этого алгоритма
00:32:00
кубическая конечно кубический рост
00:32:03
лучший экспоненциального но в целом не
00:32:07
очень хороший для больших проблем для
00:32:10
больших проблем
00:32:11
кубический рост это нехороший рост и в
00:32:14
случае большого N ждать результатов
00:32:17
придется долго
00:32:19
квадратический рост лучше кубического и
00:32:23
такие алгоритмы как правило имеют
00:32:25
двойное вложенный цикл то есть for
00:32:26
вложенный в for в качестве примеров
00:32:28
таких алгоритмов можно выделить
00:32:32
сортировку выборками и вставками Вот они
00:32:35
имеют квадратический рост квадратический
00:32:37
рост уже конечно ближе к в кавычках
00:32:41
хорошим порядком роста но по-прежнему
00:32:46
У меня очень больших проблем не является
00:32:50
практически выполнимым то есть зачастую
00:32:52
для больших задач результатов не
00:32:55
дождешься Что называется линейный
00:32:57
логарифмический рост это вот первый
00:33:00
такой порядок роста который в
00:33:03
большинстве случаев уже достаточно для
00:33:05
решения весьма больших проблем для
00:33:09
решения проблем очень большого размера
00:33:11
если временная сложность вашего
00:33:14
алгоритма линейного логарифмическая то
00:33:17
это уже надо сказать Хорошее достижение
00:33:19
такие производительные алгоритмы
00:33:22
сортировки как сортировка слияниями
00:33:24
которые также называются мерч сорт или
00:33:26
быстрая сортировка которая также
00:33:28
называется quicksort демонстрируют как
00:33:30
раз вот этот самый линейный
00:33:32
логарифмический рост линейный
00:33:34
логарифмический рост зачастую
00:33:37
достигается в алгоритме применением так
00:33:41
называемого принципа разделяя и властвуй
00:33:43
Ну то есть когда алгоритм для решения
00:33:45
проблем базиру на этом принципе вот как
00:33:48
раз алгоритм сортировки слияниями
00:33:50
базируется на этом самом принципе
00:33:52
разделяя властвуй и Именно поэтому он
00:33:55
показывает временную сложность
00:33:57
характеризуемую линейно логарифмическим
00:34:00
ростом линейный рост лучше линейный
00:34:03
логарифмического и такие алгоритмы как
00:34:06
правило имеют просто один Ford цикл
00:34:09
внутри который конечно же зависит от N
00:34:11
потому что в цикле формы идем до n я бы
00:34:15
сказал что логарифмический Рост он самый
00:34:18
лучший По той простой причине что с
00:34:20
алгоритмами временная сложность которых
00:34:22
равна константе мы на практике не
00:34:25
встречаемся поэтому о них говорить
00:34:26
просто смысла нет логарифмическая
00:34:29
временная сложность может быть
00:34:30
достигнута когда мы делим входной набор
00:34:33
данных пополам на каждой итерации
00:34:36
например бинарный поиск Вот он
00:34:39
базируется на таком принципе я бинарном
00:34:41
поиске Мы кстати говоря в дальнейшем
00:34:43
будем говорить И вот этот самый бинарный
00:34:45
поиск он демонстрирует логарифмическую
00:34:47
временную сложность как я упомянул Мы
00:34:51
никогда не работаем с алгоритмами
00:34:53
временная сложность которых показывает
00:34:55
константный рост ну Дело в том что вот
00:34:59
все раздельные операции такие как
00:35:01
сложение вычитание доступ к элементу
00:35:05
массива по индексу и так далее они вот
00:35:09
имеют как раз временную сложность равную
00:35:11
константе но простые операции глупо
00:35:15
просто их воспринимать как алгоритмы
00:35:17
поэтому константный Рост он больше
00:35:19
служит для оценки простейших частей
00:35:23
алгоритма которые не повторяются и чаще
00:35:27
всего те части алгоритма который
00:35:30
работают за константу не повторяются мы
00:35:33
как правило из уравнения описывающего
00:35:36
временную сложность их можем просто
00:35:38
вырезать я добавил ссылку на svg файл
00:35:42
Википедии где демонстрируются графики
00:35:45
функций описывающих временную сложность
00:35:48
алгоритмов можете пройти по ссылке и
00:35:51
просто для интереса посмотреть на
00:35:53
визуализацию А теперь перейдем к такому
00:35:55
понятию как О большое Вот это самое
00:35:58
большое или как по-английски говорят Big
00:36:01
All или Big own atation Ну то есть бекон
00:36:04
нотация является частью семейства
00:36:08
асимптотических нотаций О большое
00:36:10
определяет функцию которая описывает
00:36:13
самый худший случай алгоритма Вы можете
00:36:17
видеть это вот на картинке Ну что такое
00:36:20
самый худший случай алгоритма Ну Дело в
00:36:22
том что алгоритм зависит от входных
00:36:25
данных в зависимости от входных данных
00:36:28
алгоритм может демонстрировать лучший
00:36:30
случай худший и средний мы почти всегда
00:36:33
заинтересованы в оценке самого худшего
00:36:36
случая Хотя надо сказать что оценки
00:36:38
лучшего и худшего случаев также иногда
00:36:40
бывают достаточно ценны вот собственно в
00:36:45
кавычках плохой на данных будет являться
00:36:48
так называемым wordkees худшем случаем
00:36:51
для алгоритма речь идет именно об этом
00:36:53
Sigma большое определяет лучший случай а
00:36:56
тета большое несколько более хитрое это
00:37:00
большое определяет функцию которая с
00:37:03
разными константами
00:37:04
ограничивает сверху и снизу функцию FN
00:37:08
мы не будем погружаться больно глубоко
00:37:10
во всякие математические рассуждения Так
00:37:14
что я вернусь к своему
00:37:16
изначальному утверждению я сказал что в
00:37:19
большинстве случаев мы заинтересованы в
00:37:22
худших случаях в верхней границе другими
00:37:25
словами и как раз для оценки худших
00:37:28
случаев мы и используем большое
00:37:30
преимущество оценки худшего случая
00:37:33
заключается в том что полагаясь на
00:37:35
худший случай мы гарантируем что время
00:37:39
исполнения программы не превысит
00:37:41
определенный пределы которые могут быть
00:37:44
вычислены с помощью функции описывающей
00:37:47
этот самый худший случай
00:37:50
До новых встреч Подписывайтесь и ставьте
00:37:53
колокольчик а комменты пишите под видео
00:37:56
если не подпишешься вычислил по IP

Описание:

Подписывайтесь на телеграм канал: https://t.me/engineerspock_it Курсы от EngineerSpock: https://vk.cc/cnsU5i Купить полный курс по алгоритмам и структурам данных с картой РФ: https://vk.cc/cp4lKW промокод YOUTUBE Купить полный курс на udemy с картой не РФ: https://www.udemy.com/course/algodata/?referralCode=06C6A3F40168553EDEA1 Подписка на Boosty: https://boosty.to/engineerspock Донаты на развитие: https://pay.cloudtips.ru/p/1f080f72 ************************** В этой части курса по алгоритмам и структурам данных вы научитесь определять сколько времени и памяти потребует алгоритм для решения проблемы. На примере поиска триплетов вы увидите как работает неэффективный алгоритм и как растёт количество времени для решения проблемы в зависимости от её размера. Вы построите log-log график и научитесь производить аппроксимацию для оценки временной сложности. Вы познакомитесь с классическими порядками роста: константа, логарифмический, линейный и т.д. Познакомитесь с нотацией О большое. 00:00 Приветственное слово 00:37 Введение в анализ алгоритмов 16:13 Построение графика роста времени выполнения 22:28 Аппроксимация и порядок роста 29:47 Порядок роста / Временная сложность / Нотация О большое

Готовим варианты загрузки

popular icon
Популярные
hd icon
HD видео
audio icon
Только звук
total icon
Все форматы
* — Если видео проигрывается в новой вкладке, перейдите в неё, а затем кликните по видео правой кнопкой мыши и выберите пункт "Сохранить видео как..."
** — Ссылка предназначенная для онлайн воспроизведения в специализированных плеерах

Вопросы о скачивании видео

mobile menu iconКак можно скачать видео "Курс · Алгоритмы и структуры данных # ч.2 # Временная сложность и Анализ алгоритмов"?mobile menu icon

  • Сайт http://unidownloader.com/ — лучший способ скачать видео или отдельно аудиодорожку, если хочется обойтись без установки программ и расширений. Расширение UDL Helper — удобная кнопка, которая органично встраивается на сайты YouTube, Instagram и OK.ru для быстрого скачивания контента.

  • Программа UDL Client (для Windows) — самое мощное решение, поддерживающее более 900 сайтов, социальных сетей и видеохостингов, а также любое качество видео, которое доступно в источнике.

  • UDL Lite — представляет собой удобный доступ к сайту с мобильного устройства. С его помощью вы можете легко скачивать видео прямо на смартфон.

mobile menu iconКакой формат видео "Курс · Алгоритмы и структуры данных # ч.2 # Временная сложность и Анализ алгоритмов" выбрать?mobile menu icon

  • Наилучшее качество имеют форматы FullHD (1080p), 2K (1440p), 4K (2160p) и 8K (4320p). Чем больше разрешение вашего экрана, тем выше должно быть качество видео. Однако следует учесть и другие факторы: скорость скачивания, количество свободного места, а также производительность устройства при воспроизведении.

mobile menu iconПочему компьютер зависает при загрузке видео "Курс · Алгоритмы и структуры данных # ч.2 # Временная сложность и Анализ алгоритмов"?mobile menu icon

  • Полностью зависать браузер/компьютер не должен! Если это произошло, просьба сообщить об этом, указав ссылку на видео. Иногда видео нельзя скачать напрямую в подходящем формате, поэтому мы добавили возможность конвертации файла в нужный формат. В отдельных случаях этот процесс может активно использовать ресурсы компьютера.

mobile menu iconКак скачать видео "Курс · Алгоритмы и структуры данных # ч.2 # Временная сложность и Анализ алгоритмов" на телефон?mobile menu icon

  • Вы можете скачать видео на свой смартфон с помощью сайта или pwa-приложения UDL Lite. Также есть возможность отправить ссылку на скачивание через QR-код с помощью расширения UDL Helper.

mobile menu iconКак скачать аудиодорожку (музыку) в MP3 "Курс · Алгоритмы и структуры данных # ч.2 # Временная сложность и Анализ алгоритмов"?mobile menu icon

  • Самый удобный способ — воспользоваться программой UDL Client, которая поддерживает конвертацию видео в формат MP3. В некоторых случаях MP3 можно скачать и через расширение UDL Helper.

mobile menu iconКак сохранить кадр из видео "Курс · Алгоритмы и структуры данных # ч.2 # Временная сложность и Анализ алгоритмов"?mobile menu icon

  • Эта функция доступна в расширении UDL Helper. Убедитесь, что в настройках отмечен пункт «Отображать кнопку сохранения скриншота из видео». В правом нижнем углу плеера левее иконки «Настройки» должна появиться иконка камеры, по нажатию на которую текущий кадр из видео будет сохранён на ваш компьютер в формате JPEG.

mobile menu iconСколько это всё стоит?mobile menu icon

  • Нисколько. Наши сервисы абсолютно бесплатны для всех пользователей. Здесь нет PRO подписок, нет ограничений на количество или максимальную длину скачиваемого видео.