与渐进分析有何不同?您何时使用它,为什么?
我读过一些写得不错的文章,例如:
http://www.ugrad.cs.ubc.ca/~cs320/2010W2/handouts/aa-nutshell.pdf
http://www.cs.princeton.edu/~fiebrink/423/AmortizedAnalysisExplained_Fiebrink.pdf
但我仍然没有完全理解这些概念。
那么,有人可以为我简化一下吗?
与渐进分析有何不同?您何时使用它,为什么?
我读过一些写得不错的文章,例如:
http://www.ugrad.cs.ubc.ca/~cs320/2010W2/handouts/aa-nutshell.pdf
http://www.cs.princeton.edu/~fiebrink/423/AmortizedAnalysisExplained_Fiebrink.pdf
但我仍然没有完全理解这些概念。
那么,有人可以为我简化一下吗?
Answers:
摊销分析不会天真地将调用次数与一次调用的最坏情况相乘。
例如,对于需要时将大小增加一倍的动态数组,正常的渐近分析只会得出结论,将一个项目添加到该数组中会花费O(n),因为它可能需要增长并将所有元素复制到新数组中。摊销分析考虑到要增长,必须添加n / 2个项目,而自上一次增长起就不会导致增长,因此添加项目实际上只需要O(1)(O(n)的成本为分摊到n / 2个操作中)。
摊销分析与“平均绩效”不同-摊销分析为如果您执行大量操作将对绩效产生硬性保证。
对于“什么”有很多答案,但对于“为什么”却没有答案。
正如其他所有人所说,渐进分析是关于给定操作的性能如何扩展到大型数据集。摊销分析是关于大型数据集上所有操作的平均性能如何扩展的。摊销分析永远不会给出比渐近更差的界限,有时会给出更好的界限。
如果您担心较长工作的总运行时间,则可能要考虑摊销分析的更好范围。这就是为什么脚本语言(例如)经常乐于以某种方式增长数组和哈希表,即使这是一项昂贵的操作。(增长可以是一项O(n)
操作,但摊销是O(1)
因为您很少这样做。)
如果您正在进行实时编程(单个操作必须在可预测的时间内完成),则摊销分析的更好界限并不重要。平均操作速度是否快,是否没有及时完成操作以在切割得太远之前调回带锯都没有关系...
在您的情况下,哪一个重要取决于确切的编程问题。
该术语是指在对算法进行操作的数据(输入)用外行的话来说是“大到足以使其变大不会改变结论”的假设下对算法性能的分析。虽然不需要输入的准确大小不被指定(我们只需要一个上限),该数据集本身具有被指定。
请注意,到目前为止,我们仅讨论了分析方法。我们没有确切指定要分析的数量(时间复杂度?空间复杂度?),也没有指定我们感兴趣的度量标准(最坏情况?最佳情况?平均值?)。
在实践中,术语“渐近分析”通常是指算法的上限时间复杂度,即,以总运行时间衡量的最坏情况性能,用big-Oh表示法表示(例如,排序算法可能是O(nlogn)
)。
该术语指的是基于针对最坏情况的特定操作序列对算法性能进行的分析-也就是说,摊销分析确实表明该指标是最坏情况的性能(尽管仍然没有说要测量哪个数量) )。要执行此分析,我们需要指定输入的大小,但是我们不需要对其输入形式进行任何假设。
用外行的术语来说,摊销分析是为输入选择任意大小,然后“遍历”算法。每当必须根据输入做出决定时,都会采取最差的做法¹。算法运行完成后,我们将计算出的复杂度除以输入的大小以产生最终结果。
¹注意:确切地说,理论上可能的最坏路径。如果您的向量每次容量耗尽时都会动态加倍,“最坏情况”并不意味着假定每次插入都需要加倍,因为插入是按序列处理的。即使在输入仍然未知的情况下,我们也被允许(并且确实必须)使用已知状态以数学方式消除尽可能多的“甚至更糟”的情况。
渐近分析与摊销分析之间的关键区别在于,前者取决于输入本身,而后者则取决于算法将执行的操作顺序。
因此:
O(1)
。
答案由《摊销分析》一书的第一句话-算法简介简要定义:
在摊销分析中,执行一系列数据结构操作所需的时间在所有执行的操作中平均。
我们通过渐近分析来表示程序增长的复杂性-通过函数来限制程序的增长,并定义最坏,最好或平均的情况。
但是,在仅一种情况下,程序的复杂性达到顶峰的情况下,这可能会产生误导,但总的来说,该程序不需要太多的计算。
因此,即使单个操作可能很昂贵,也要对一系列操作进行平均费用才有意义。这是摊销分析!
摊销分析是渐进技术的替代方法,用于计算复杂度。它可以帮助我们根据实用性计算出更真实的复杂度,以便在两个或多个算法之间进行比较和确定。
到目前为止,我找到的关于理解算法的摊销分析的最佳参考是《算法简介》第三版,第17章:“摊销分析”。一切都在这里,比在Stack Overflow帖子中可以找到的解释要好得多。您可以在任何体面的大学的图书馆中找到这本书。
摊销分析处理了该例程多次运行的总成本以及可从中获得的收益。例如,搜索n个项目的未排序数组以进行单个匹配可能需要进行n次比较,因此复杂度为o(n)。但是,如果我们知道要在同一数组中搜索m个项目,那么重复整个任务将具有O(m * n)的复杂度。但是,如果我们预先对数组进行排序,则成本为O(n log(n)),并且连续搜索仅需要O(log(n))即可获得排序后的数组。因此,采用这种方法的m个元素的总摊销成本为O(n * log(n)+ m * log(n))。如果m> = n,则与不进行排序的O(n ^ 2)相比,通过预排序就等于O(n log(n))。因此,摊销成本更便宜。
简而言之,通过尽早花一些额外的钱,我们可以在以后节省很多。