Рекурсия и большой 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), и это экспоненциальный.