Лекция 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 < означает, что стандартный ввод берется из файла input.txt \> означает, куда выводится стандартный вывод.

Останется сравнить ваш 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, но обычно этого достаточно для анализа алгоритма.

Двоичный поиск

Найти указанный элемент в отсортированном массиве.