Рекурсия - это способ решения задач с помощью разбиения их на всё меньшие и меньшие подзадачи до тех пор, пока результат не сможет быть найден тривиальным способом.
Пин-код от телефона состоит из четырёх цифр. Вы помните цифры кода и то, что они все разные, но забыли в каком порядке они расположены. Сколько, в худшем случае, комбинаций этих цифр вам нужно перебрать, чтобы разблокировать телефон?
Поиск ответа сводится к вычислению факториала: \(4!\)
\[ n! = n \cdot (n-1)! \]
Используем рекурсию для перевода числа из десятичной системы счисления в двоичную.
Используем рекурсивный алгоритм для вычисления \(n\)-го числа последовательности.
\(F(0)=0\), \(F(1) = 1\).
\[F(n)=F(n-1) \cdot F(n-2)\]
Рекурсивный алгоритм может содержать несколько базовых случаев для тривиальных решений подзадач.
если базовый случай 1, то:
вернуть решение 1
если базовый случай 2, то:
вернуть решение 2
. . .
если рекурсивный случай 1, то:
инструкции до рекурсии
рекурсивный вызов алгоритма
инструкции после рекурсии
если рекурсивный случай 2, то:
инструкции до рекурсии
рекурсивный вызов алгоритма
инструкции после рекурсии
. . .Используем рекурсивный алгоритм, чтобы определить, является ли число простым или составным.
Динамическое программирование - метод решения задач оптимизации и подсчёта.
Суть метода - сохранение промежуточных вычислений для их повторного использования. Промежуточные решения являются решением подзадач.
Подзадача - задача с меньшим количеством параметров или меньшими значениями параметров.
Решения подзадач сохраняются в одномерных или двухмерных таблицах (массивах или матрицах).
Вычислите \(n\)-ое число Фибоначчи. \[ F(0)=0; F(1)=1; F(n)=F(n-1)+F(n-2) \]
Робот движется по клеткам поля размером M x N. Он начинает своё движение в верхнем левом углу и движется в нижний правый угол поля. Робот может двигаться только вниз или вправо.
Сколькими различными способами робот может попасть в целевую клетку.
\[ grid(2, 3)=? \]
\[ grid(2, 3)=3 \]
\[ grid(1, 1)=1 \]
\[ grid(0, 2) = 0 \]
Решение крупной задачи сводится к подзадачам с меньшими значениями аргументов.
Элемент матрицы с индексом [M, N] будет хранить решение задачи для поля размером M x N.
Определить набор параметров, которые уникальным образом описывают разные со стояния задачи.
Создать таблицу, размерность и количество элементов в которой зависит от количества параметров задачи. Элемент таблицы будет хранить решение подзадачи для выбранного набора параметров.
Тип элементов таблицы зависит от ожидаемого результата.
Инициализировать значения таблицы начальными значениями - решениями тривиальных подзадач.
Перебрать элементы таблицы и заполнить следующие элементы таблицы с помощью значения текущего элемента. Продолжать, пока вся таблица не будет заполнена.
Зачастую ответ будет храниться в последнем элементе таблицы.
Динамическое программирование - компромисс между временем выполнения алгоритма и объёмом используемой памяти.
Дан массив целых неотрицательных чисел. Определить, можно ли получить число \(sum\) путём сложения чисел в массиве. Каждое число в массиве можно использовать неограниченное количество раз. \[ canSum(7, [5, 3, 4])=True \]
\[ canSum(8, [5, 7])=False \]
В качестве решённой подзадачи используем вариант, когда \(sum=0\):
\[ canSum(0, [1, 2, 3]) = True \]
\[ canSum(5, [2, 3, 4])=? \]
Рекурсивное вычисление чисел Фибоначчи:
Мемоизация - техника запоминания промежуточных результатов рекурсивных вызовов функции.