Лекция 1
Сайт со всей информацией: http://students.iposov.spb.ru Прямая ссылка на курс https://students.iposov.spb.ru/21spring/algs/
Программы с реализациями алгоритмов будут проверяться на тестах. Текущий вариант: я выдаю тесты, вы сами запускаете на них программы. Возможно, перейдем на Stepic.
Язык программирования: выбираете сами. Крайне рекомендуется «обычный», императивный язык: C++, Java, Pascal, C#, Python.
Пишем консольные программы. (без графического интерфейса) Программа запускается, берет данные из стандартного входа (stdin), выводит результат в стандартный вывод (stdout). Мне кажется, это лучше, чем чтение из файла input.txt и запись в output.txt. В этом случае придется менять в программе имена файлов с тестами, перекомпилировать их.
В win консоли, в linux, в mac:
program.exe
Останется сравнить ваш output.txt и мой.
Еще один принцип: не беспокоиться об ошибках во входных данных, отсутствии файлов или прав на чтение. При чтении данных не нужно писать проверок на ошибки, т.е. тратить на это время.
Как сдавать задания: Если я выдаю задачу, то, фактически, я выдаю ссылку на условие и возможность загрузки решения.
Сложность алгоритма
Алгоритм получает на вход данные, выполняет с ними определенное количество действий. Вы сами определяете, что именно считать действиями алгоритма. От тактов процессора до количества арифметических операций.
Количество действий = F(входные данные)
Входные данные имеют размер, его можно считать в байтах, в цифрах, в вершинах графа и т.п.
Оценить сложность алгоритма, это оценить количество действий сверху: Количество действий <= G(n), где n - это размер входных данных.
G(n) - это и есть сложность алгоритма.
Пример. Проверим число на простоту.
n = число для проверки
for i = 2 до sqrt(n)
if n делится на i
return false // не простое!
return true;
Если мы считаем размером входных данных величину числа n, а действиями мы считаем арифметические операции (деление, увеличение i на 1)
Тогда сложность sqrt(n), т.е. кол-во действий <= sqrt(n)
Но на практике, число вводится как набор цифр. Т.е. число N вводится примерно как log10(N). Размер входных данных n = log10(N) Кол-во действий делений это
кол-во действий <= sqrt(N) = sqrt(10^n) = = 10 ^ (n / 2) ~ 3 ^ n
Если считать, что мы работаем с длинными числами, то операция деления уже не атомарна. Вспомните, сколько вы делаете действий, когда делите одно число на другое в столбик. Наивная реализация, при делении числа из k цифр на число из l цифр требует написать около k*l цифр.
Т.е. количество действий <= 3^n * (n * n) <=n * n действий для каждого деления
Асимптотическая оценка сложности.
3^n * (n*n) - с этим может быть неудобно работать, слишком много действий в функции.
кол-во действий <= 3^n * (nn) < C * 4^n , где C какая-то константа. 4^n / (3^n(n*n)) -> oo при n -> oo и неравенство выполнено, начиная с какого-то n.
кол-во действий = O(4^n). Неизвестно ни с какого n выполняется неравенство, неизвестно, какая константа C, но обычно этого достаточно для анализа алгоритма.
Двоичный поиск
Найти указанный элемент в отсортированном массиве.