Рекурсия и большой O
Я работал над недавним домашним заданием по информатике, включающим рекурсию и нотацию big-O. Я думаю, что понимаю это довольно хорошо (конечно, не совсем, хотя!) Но есть один вопрос, в частности, что дает мне больше всего проблем. Странно то, что, глядя на него, он выглядит самым простым в домашнем задании.
обеспечить наилучшую скорость роста, используя нотацию big-Oh для решения следующего повторения?
T (1) = 2
T(n) = 2T (n - 1) + 1 для n>1
и выбор, являются:
- O (N log n)
- O (n^2)
- O (2^n)
- O (n^n)
Я понимаю, что big O работает как верхняя граница, чтобы описать наибольшее количество вычислений или наибольшее время работы, которое займет программа или процесс. Я чувствую, что эта конкретная рекурсия должна быть O (n), так как, самое большее, рекурсия происходит только один раз для каждого значение n. Поскольку n недоступен, это либо лучше, чем это, O(nlogn), либо хуже, будучи тремя другими вариантами.
Итак, мой вопрос: почему это не O (n)?
7 ответов
существует несколько различных способов решения рецидивов: подстановка, дерево рецидивов и главная теорема. Основная теорема не будет работать в этом случае, потому что она не соответствует форме основной теоремы.
вы можете использовать два других метода, но самый простой способ для этой проблемы-решить ее итеративно.
T(n) = 2T (n-1) + 1
T(n) = 4T (n-2) + 2 + 1
T (n) = 8T(n-3) + 4 + 2 + 1
T (n) = ...
посмотреть шаблон?
T (n) = 2n-1⋅T (1) + 2n-2 + 2n-3 + ... + 1
T (n) = 2n-1⋅2 + 2n-2 + 2n-3 + ... + 1
T (n) = 2n + 2n-2 + 2n-3 + ... + 1
поэтому самая тесная граница-Θ (2n).
Я думаю, вы немного неправильно поняли вопрос. Он не спрашивает вас, сколько времени потребуется, чтобы решить рецидива. Он спрашивает, Что такое big-O (асимптотическая граница) самого решения.
то, что вам нужно сделать, это придумать решение закрытой формы, i. e. нерекурсивная формула для T (n), а затем определить, что такое big-O этого выражения.
вопрос задает для обозначения big-Oh для решения повторения, а не стоимость расчета повторения.
другими словами: повторение производит:
1 -> 2
2 -> 5
3 -> 11
4 -> 23
5 -> 47
какая большая-Oh нотация лучше всего описывает последовательность 2, 5, 11, 23, 47, ...
правильный способ решить это-решить рекуррентные уравнения.
Я думаю, что это будет экспоненциальный. Каждое приращение к n делает значение в два раза больше.
T(2) = 2 * T(1) = 4
T(3) = 2 * T(2) = 2 * 4
...
T (x) будет временем выполнения следующей программы (например):
def fn(x):
if (x == 1):
return # a constant time
# do the calculation for n - 1 twice
fn(x - 1)
fn(x - 1)
Я думаю, что это будет экспоненциальный. Каждое приращение к n приносит вдвое больше вычислений.
нет, это не так. Совсем наоборот:
считаю, что для n итерации, мы получаем время работы R. Тогда для n + 1 итерации мы получим точно R + 1.
таким образом, скорость роста постоянна и общее время выполнения действительно O(n).
тем не менее, я думаю, что предположение Димы о вопросе правильно, хотя его решение слишком сложно:
то, что вам нужно сделать, это придумать решение закрытой формы, i. e. нерекурсивная формула для T (n), а затем определить, что такое big-O этого выражения.
достаточно изучить относительный размер T(n) и T(n + 1) итерации и определение относительной скорости роста. Сумма, очевидно, удваивается, что непосредственно дает асимптотический рост.
во-первых, все четыре ответа хуже, чем O(n)... O(n * log n) сложнее, чем обычный старый O (n). Что больше: 8 или 8 * 3, 16 или 16 * 4, и т. д...
к актуальному вопросу. Общее решение, очевидно, может быть решено в постоянное время, если вы не делаете рекурсию
(T(n) = 2^(n - 1) + 2^(n) - 1 ), так что это не то, что они просят.
и как вы можете видеть, если мы напишем рекурсивный код:
int T( int N )
{
if (N == 1) return 2;
return( 2*T(N-1) + 1);
}
Это очевидно O (n).
таким образом, это, по-видимому, плохо сформулированный вопрос, и они, вероятно, задают вам рост самой функции, а не сложность кода. Это 2^n. А теперь иди делай домашнюю работу... и учиться на O (N * log n)
вычисление решения замкнутой формы для рекурсии легко. При осмотре, вы догадываетесь, что решение
T(n) = 3*2^(n-1) - 1
тогда вы доказываете индукцией, что это действительно решение. Базовый вариант:
T(1) = 3*2^0 - 1 = 3 - 1 = 2. OK.
индукции:
Suppose T(n) = 3*2^(n-1) - 1. Then T(n+1) = 2*T(n) + 1 = 3*2^n - 2 + 1 = 3*2^((n+1)-1) - 1. OK.
где первое равенство вытекает из определения рецидива , и второе из индуктивной гипотезы. КЭД.
3 * 2^(n-1) - 1 явно тета (2^n), следовательно, правильный ответ третий.
людям, которые ответили O (n): я не могу не согласиться с Димой. Проблема не попросите самую жесткую верхнюю границу вычислительной сложности алгоритма вычислить T (n) (которая теперь будет O (1), так как ее замкнутая форма была предоставлена). Проблема требует самой жесткой верхней границы на самом T (n), и это экспоненциальный.