Я считаю, что простой способ понять это - рассмотреть время, которое алгоритм тратит на каждый шаг повторения, а затем сложить их, чтобы найти общее время.Сначала давайте рассмотрим
T(n) = T(n/2) + O(1)
, где n = 64.Давайте сложим, сколько алгоритм занимает на каждом шаге:
T(64) = T(32) + 1 ... 1 so far
T(32) = T(16) + 1 ... 2 so far
T(16) = T(08) + 1 ... 3 so far
T(08) = T(04) + 1 ... 4 so far
T(04) = T(02) + 1 ... 5 so far
T(02) = T(01) + 1 ... 6 so far
T(01) = 1 ... 7 total
Итак, мы можем видеть, что алгоритм занимает «1» время на каждом шаге.И, так как каждый шаг делит входные данные пополам, общая работа - это количество раз, которое алгоритм должен был разделить входными данными на два ... что составляет log2 n.
Далее, давайте рассмотрим случай, когда
T(n) = 2T(n/2) + O(1)
Однако, чтобы упростить ситуацию, мы будем строить из базового случая T (1) = 1.
T(01) = 1 ... 1 so far
, теперь мы должны сделать T (01) дваждыи затем добавьте один, так что
T(02) = 2T(01) + 1 ... (1*2)+1 = 3
теперь мы должны сделать T (02) дважды, а затем добавить один, так что
T(04) = 2T(02) + 1 ... (3*2)+1 = 7
T(08) = 2T(04) + 1 ... (7*2)+1 = 15
T(16) = 2T(08) + 1 ... (15*2)+1 = 31
T(32) = 2T(16) + 1 ... (32*2)+1 = 63
T(64) = 2T(32) + 1 ... (65*2)+1 = 127
Итак, мы можем видеть, что здесь алгоритм имеетвыполнено 127 работ - что равно входу, умноженному на константу (2) и плюс константу (-1), которая равна O (n).По сути, эта рекурсия соответствует бесконечной последовательности (1 + 1/2 + 1/4 + 1/8 + 1/16), сумма которой равна 2.
Попробуйте использовать этот метод для T (n) = 2T (n / 2) + n и посмотрите, имеет ли это для вас смысл.