平摊分析 Amortized Analysis ------geeksforgeeks翻译
当偶尔一切操作很花的时间很慢,而大多数操作的时间都很快的时候,平摊分析的方法就很很好用了。在平摊分析中,我们分析一串操作并且可以得到最坏情况下的平均时间复杂度。例如hash table, disjoint set 和splay tree都是用平摊分析算法的。
举一个简单的hash table的插入算法,我们怎么来定义hash table的大小呢?这是一个时间和空间的权衡(trade-off)。如果让hash table空间大的话,那搜索的时间会变慢,如果空间小,不一定能存的下数据。
解决这种权衡的方法是利用动态表or数组(dynamic table)。主要思想是当表已经满的时候增加哈希表的大小,步骤是:
1.给哈希表增加内存,一般是原来大小的两倍。
2.把原来的表的数据复制到新表中。
3.释放旧表的内存。
(有点类似java中 string 拼接的感觉)
这种哈希表的插入算法的时间复杂度是多少呢?
如果我们简单的分析,插入一个元素的最坏复杂度是O(n),(解释一下,因为这时哈希表可能满,需要复制n个元素到新的大表中,所以最坏的情况是O(n) ) 所以插入n个数的时间复杂度是n*O(n) = O(n2)。 这种分给除了上界限,但不是一个最紧的上界限,因为n个元素插入,不一定没一个都需要O(n)的时间。
所以用平摊分析发,我们可以证明用动态表的话,插入一个元素的时间复杂度是O(1)。动态大小的这种方法也用于C++ 的vector 和 Java的ArrayList。
下面是一些重要的信息:
1.平摊分析可以看做一个人是如何消费的,一个人平均每个月的花销是小于或者等于他的月薪。但是它可以在这个月花更多的钱,而在其他的月份存一些钱。
2.用动态数组的平摊分析有个名字叫做aggregate method (总体成本法),有两个厉害的方法去平摊分析:accounting method , potential method
3.平摊分析法和概率没啥关系,还有一些别的概念去分析一些用随机算法来减少算法的时间复杂度。这种方法叫做随机算法 Randomized Analysis。例如 随机化的快速排序(quick sort),快速选择(quick select,或者散列函数(hashing)。我们会在之后会的文章中提到这些内容