当我们遨游在分治法的海洋中时,有一个问题不得不关注——分治算法的时间复杂度如何计算?
本文,我们将对分治法的时间复杂度建模,用数学方法分析它的渐进特性,并给出三种计算方式。
从分治法到递归式
所谓分治法,就是把大问题分解成小问题,再把小问题的解合并成原问题的解。递归式则是用数学语言对这一过程的时间代价建模。
从一个案例入手更容易理解。以上一篇文章归并排序为例,我们用
表示原问题的时间复杂度,其中
为输入数据的规模。第一次拆分,将原数据拆解为等大小的两份,各为
,然后对这两份各自递归调用归并排序,这部分工作的时间复杂度为
。最后将这两个排好序的子数组合并,所需的时间复杂度是
。
根据以上分析,我们可以写出归并排序的递归式
可以想象,对于任意一种分治算法,其时间复杂度都可以用递归式表示。递归式的右侧通常由两部分组成,第一部分是分解后子问题的总代价,第二部分是分解和合并子问题的总代价。第一部分仍然是
的函数,第二部分则是实际的渐进复杂度。
有了递归式,并不能看出该算法的时间复杂度到底是多少,我们需要进一步计算出
真正的解。
代入法
递归式求解的第一种方法称为代入法。我们需要先猜出解的形式,然后用数学归纳法证明该猜测是正确的。
对于式(4.1),假设我们猜测它的解是
。如果把渐进符号去掉,该式就等价于
,其中
为任意正常数。
根据数学归纳法,首先我们要确定当
比较小时该猜测成立。当
时,由式(4.1)可知,
,其中
是某个大于0的常数。根据猜测,我们希望
,可是,无论怎样取
,该式都不可能成立,因为
必然大于0。数学归纳法还没开始就失败了。
不过不必担心,这只是一个
导致的特殊情况,我们完全可以把数学归纳法的初始状态放在
的位置,同时不影响数学归纳法的结果。因为我们只关心当
足够大时
的渐进性质,而不关心初始阶段。
现在,令
,则
,我们希望
成立,化简后得
,由于
和