当我正在阅读一篇有关Yoneda引理的论文时,我发现它与光学学的关系,我遇到了以下陈述:
... Cayley's mono半定理(这是启用累加参数的技巧, 经常可以将二次时间程序变成线性时间程序)。
我感兴趣的部分是the trick ... quadratic-time... into a linear-time one
。它是如何工作的?
P.S。我对Monoid和常用的数学符号很熟悉,因此如有必要,可以随时使用它,也可以坚持使用Haskell。
答案 0 :(得分:2)
在H. Bird的原始论文之后,该主张的主要示例是简单链接列表的列表反转,可以定义为
reverse([a : x]) = append(reverse x, a)
在直接实现中,要将a
附加到尾部x
的反面,需要进行n-1
查找操作才能找到结尾,并且该操作计数为reverse x
,因此总工作量为(n-1)+...+2+1=n*(n-1)/2
。
线性实现使用append
操作的非对称复杂度,因为append(x,y)
的开销与x
的长度成正比,而y
的长度不起作用任何角色。作为append
的部分运算,是列表append(x) y = append(x,y)
上的同构。
现在将颠倒的列表表示为这些内态同构的结果
reverse([a1,a2,...,an])=append(an) ... append(a2) append(a1) []
,列表重建是从中进行的线性成本操作。先前的二次“主”成本在操作堆栈的管理中被“隐藏”。但是,最终并不需要这样做,因为结果列表的重建可以从提取第一个元素开始。这需要使用相同的野生伪代码的“累加元素”
reverse(x) = reverse_recursion(x,[])
其中
reverse_recursion([a : x], y) = reverse_recursion(x, [a : y])
与
reverse_recursion([], y) = y