вторая часть

advertisement
Методика и содержание подготовки учащихся к олимпиадам по программированию.
Дистанционный курс.
Оценка эффективности алгоритмов
Помимо проверки того, что алгоритм, реализованный школьником в качестве решения способен
выдать правильный ответ задачи к при тех или иных исходных данных, при проверке решения
также учитывается и время работы программы. Это не значит, то жизненно необходимо во всех без
исключения задачах писать оптимальные алгоритмы (которые, зачастую могут отнять много
времени на их грамотную реализацию и отладку). Это просто означает, что в некоторых отдельных
задачах параметр времени может играть очень важную роль. Вполне может случиться, что на
каком-нибудь олимпиадном туре вообще не будет ни одной задачи, в которой необходима
оптимальность. Однако, может случиться и наоборот.
Таким образом и школьники, и преподаватели должны уметь сравнивать разные алгоритмы по их
эффективности. Школьники — для того, чтобы выбрать в нужный момент наиболее подходящий
способ решения задачи, преподаватели — чтобы грамотно подбирать задачи и понимать, какое
решение подразумевал автор той или иной задачи, задавая именно такие ограничения по времени.
Для оценки эффективности алгоритма применяется функция сложности, обозначаемая O (читается
«о большое»). На самом деле есть и другие оценки, но на этапе когда школьник только-только
начинает знакомиться с различными алгоритмами они не очень нужны.Функция сложности
отражает по какой закономерности будет расти время выполнения программы в зависимости от
исходных данных или их количества.
В качестве примера алгоритма, время выполнения которого зависит от исходного данного —
алгоритм нахождения всех натуральных делителей числа N. Очевидно, что чем больше число, тем
больше шагов цикла будет необходимо сделать. Примером алгоритма, время выполнения которого
зависит от количества входных данных будет поиск наибольшего числа в массиве. Чем длиннее
массив, тем больше операций сравнения необходимо сделать, чтобы определить какое число
является наибольшим.
Функцией сложности алгоритма будем считать O(f(N)) (здесь f() - некоторая функция от исходных
данных), если для любого N существует такая константа C, что время выполнения (или количество
операций) не превышает Cf(N).
Основными функциями являются:
 O(1) — такая функция сложности говорит о том, что время работы программы постоянно
при любых исходных данных;
 O(N) — количество операций растет пропорционально N (здесь N может быть как
параметром задачи, так и количеством элементов в массиве).
 O(log N) — количество операций растет пропорционально логарифму N (именно такой
сложностью обладает, например, метод половинного деления при поиске элемента в
упорядоченном массиве). При увеличении N на порядок количество операций меняется на
единицу. Основание логарифма обычно не уточняется, нас интересует характер роста
(быстро/медленно), а не точное значение времени.
2
 O(N ) — количество операций растет пропорционально квадрату N. В общем случае может
быть O(Nk) в зависимости от сложности задачи.
 O(N!) - количество операций растет пропорционально факториалу N.
МЦНМО, 2007/08 учебный год
Методика и содержание подготовки учащихся к олимпиадам по программированию.
Дистанционный курс.
Здесь существует некоторое количество тонкостей, связанных с тем что не все операции
выполняются за одинаковое время, поэтому при оценке временной сложности используются те
операции, которые требуют наибольшего времени.
Чаще всего при описании алгоритмов приводится оценка времени их работы в чистом виде, то
есть без учета операций ввода/вывода.
Пример: оценим сложность программы, вводящей с клавиатуры массив и находящей в нем
наибольший элемент.
Алгоритм состоит из следующих шагов:
1. ввод массива (надо считать N элементов)
2. поиск наибольшего элемента (надо сделать N-1 сравнение)
3. вывод результата (надо вывести одно число или строку).
Сложим количество операций N+(N-1)+1=2N. То есть существует такая константа, что при любом
N количество операций не превышает CN. Следовательно, сложность алгоритма равна O(N).
Пример: оценим сложность программы, вводящей с клавиатуры массив и находящей в нем элемент
с заданным свойством (например, равный определенному значению).
Алгоритм состоит из следующих шагов:
1. ввод массива (N операций ввода)
2. поиск элемента с заданным свойством (как повезет: элемент может находиться как ближе к
началу массива, так и в самом конце; если элемента не существует, то необходимо сделать
все N сравнений, чтобы в этом убедиться)
3. вывод результата.
В лучшем случае данный алгоритм потребует N+2 операции (ввод всего массива, единственное
сравнение, вывод), в худшем (когда такого элемента нет — 2N+1 операцию). Если N будет
большим числом, к примеру порядка 106, то единицей можно пренебречь. Следовательно,
сложность алгоритма равна O(N).
Пример: определим функцию сложности алгоритма шифрования слова, длины L методом
подстановки. Пусть существует таблица, в которой для каждого символа алфавита записан символ,
на который его надо заменить. Обозначим количество букв алфавита S.
Алгоритм состоит из следующих шагов:
1. ввод слова (одна операция)
2. цикл по всем символам
1. для каждого символа найти его замену в таблице (если таблица не упорядочена и не
обладает какими-нибудь свойствами, облегчающими поиск, то в худшем случае S
операций для одного символа, если искомый элемент находится в самом конце)
2. вывод найденного символа
3. конец цикла
Общее количество операций 1+(S+1)*L. В случае достаточно больших S и L единицами можно
пренебречь, получится что функция сложности данного алгоритма есть O(S*L).
Пример: определим функцию сложности алгоритма перевода натурального числа N в двоичную
систему счисления (без операций ввода и вывода данных).
Алгоритм состоит из следующих шагов:
1. цикл, пока результат деления числа на 2 не станет равным 0
МЦНМО, 2007/08 учебный год
Методика и содержание подготовки учащихся к олимпиадам по программированию.
Дистанционный курс.
1. разделить число на 2 и запомнить остаток
2. принять результат деления за новое число
2. конец цикла
Общее количество операций не превышает 1+log2N. Поэтому данный алгоритм имеет сложность
O(log N).
Если программа состоит из нескольких частей с различными функциями сложности, то большая
функция сложности «поглотит» меньшие. Например, если делается ввод массива O(N), сортировка
O(N2) и вывод упорядоченного массива за O(N), то можно сказать, что вся программа имеет
сложность O(N2)
Практическое применение знаний о функиях сложности алгоритмов двояко. Во-первых, для какойто задачи можно выбрать более оптимальный алгоритм, если о нем есть соответствующие данные
в литературе. Во-вторых, зная время работы своего решения на одном наборе исходных данных,
школьник может примерно прикинуть время работы этой же программы на данных, которые
соответствуют максимальным ограничениям по данной задаче.
Вопросы
Данные задачи служат для самопроверки по изложенному материалу и не являются
обязательными.
1. Определите функцию сложности алгоритма решения квадратного уравнения.
2. Определите фукцию сложности алгоритма рисования правильного многоугольника по
заданному количеству сторон.
3. Определите функцию сложности алгоритма вставки элемента в массив на заданную
позицию (со предварительным смещением всех элементов с номерами большими либо
равными данному на одну позицию вправо).
4. Определите функцию сложности алгоритма сложения двух натуральных чисел в столбик
(пусть A — количество цифр первого числа, B — количество цифр второго).
5. Определите функцию сложности алгоритма умножения двух натуральных чисел в столбик.
МЦНМО, 2007/08 учебный год
Download