我已经写出了一个小本地计算机代数系统的递归算法,其中我将代数运算的操作数列表中的成对还原应用于相邻操作数列表,因为代数是非交换)。我想了解我的算法的运行时复杂性(但不幸的是,作为一名物理学家,自从我选修了处理复杂性分析的本科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 Theorem_? 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