Я выписал рекурсивный алгоритм для маленькой самородной системы компьютерной алгебры, где я применяю парные сокращения к списку операндов алгебраической операции (только смежные операнды, так как алгебра некоммутативное). Я пытаюсь получить представление о сложности выполнения моего алгоритма (но, к сожалению, как физик, прошло очень много времени с тех пор, как я прошел какие-либо курсы под руководством CS, которые касались анализа сложности). Не вдаваясь в подробности конкретной проблемы, я думаю, что могу формализовать алгоритм в терминах функции f
, которая является шагом «деление» и функцией g
, которая объединяет результаты. Мой алгоритм будет принимать следующее формальное представление:Анализ сложности вложенных рекурсивных функций
f(1) = 1 # recursion anchor for f
f(n) = g(f(n/2), f(n/2))
g(n, 0) = n, g(0, m) = m # recursion ...
g(1, 0) = g(0, 1) = 1 # ... anchors for g
/g(g(n-1, 1), m-1) if reduction is "non-neutral"
g(n, m) = | g(n-1, m-1) if reduction is "neutral"
\ n + m if no reduction is possible
В этих обозначениях функции f
и g
получить списки в качестве аргументов и возвращает списки, с длиной входных/выходных списков будучи аргументом и правая часть вышеприведенных уравнений.
Для полной истории, фактический код, соответствующий f
и g
следующий:
def _match_replace_binary(cls, ops: list) -> list:
"""Reduce list of `ops`"""
n = len(ops)
if n <= 1:
return ops
ops_left = ops[:n//2]
ops_right = ops[n//2:]
return _match_replace_binary_combine(
cls,
_match_replace_binary(cls, ops_left),
_match_replace_binary(cls, ops_right))
def _match_replace_binary_combine(cls, a: list, b: list) -> list:
"""combine two fully reduced lists a, b"""
if len(a) == 0 or len(b) == 0:
return a + b
if len(a) == 1 and len(b) == 1:
return a + b
r = _get_binary_replacement(a[-1], b[0], cls._binary_rules)
if r is None:
return a + b
if r == cls.neutral_element:
return _match_replace_binary_combine(cls, a[:-1], b[1:])
r = [r, ]
return _match_replace_binary_combine(
cls,
_match_replace_binary_combine(cls, a[:-1], r),
b[1:])
Я заинтересован в худшем случае число раз get_binary_replacement
является называется, в зависимости от размера ops
Вы пытались применить теорему _Master_? https://en.m.wikipedia.org/wiki/Master-Theorem – clemens
Я знал, что должна быть теорема об этом! С первого взгляда кажется, что это применимо именно к моей ситуации, я прочитаю детали и посмотрю, откуда это получается. –
@macmoonshine Я не думаю, что теорема Мастера может быть применена напрямую. Речь идет о рекурсиях типа «T (n) = aT (n/b) + f (n)», однако проблема OP имеет тип «T (n) = g (T (n/b)), T (n/c)) + f (n) 'и я не вижу простого способа уменьшить это до первой формы ... В любом случае первое, что нужно сделать, это получить сложность' g', так как это не зависит от 'f'. После этого вы просто замените два аргумента в этой сложности на 'f (n/2)', и после этого вы можете оказаться в форме теоремы Мастера, считая, что она остается линейной ... – Bakuriu