使用递归方程的程序的时间复杂度

Posted

技术标签:

【中文标题】使用递归方程的程序的时间复杂度【英文标题】:Time complexity of the program using recurrence equation 【发布时间】:2013-03-13 19:33:27 【问题描述】:

我想使用递归方程找出程序的时间复杂度。 那是..

int f(int x)

if(x<1) return 1;
 else  return f(x-1)+g(x); 

int g(int x)

if(x<2) return 1;
 else return f(x-1)+g(x/2);

我写了它的递归方程并试图解决它,但它不断变得复杂

T(n) =T(n-1)+g(n)+c
         =T(n-2)+g(n-1)+g(n)+c+c
         =T(n-3)+g(n-2)+g(n-1)+g(n)+c+c+c
         =T(n-4)+g(n-3)+g(n-2)+g(n-1)+g(n)+c+c+c+c
         ……………………….
        ……………………..
        Kth time …..
        =kc+g(n)+g(n-1)+g(n-3)+g(n-4).. .. . … +T(n-k)

Let at kth time input become 1
Then n-k=1
         K=n-1
Now i end up with this..
T(n)= (n-1)c+g(n)+g(n-1)+g(n-2)+g(n-3)+….. .. g(1)

我无法进一步解决它。 无论如何,如果我们计算这个程序中的函数调用次数,很容易看出时间复杂度是指数级的,但我想用递归来证明它。怎么办?

Anwer 1 中的解释,看起来正确,我做过类似的工作。

这段代码中最困难的任务是写出它的递归方程。我画了另一张图,我确定了一些模式,我想我们可以从这张图得到一些帮助,什么是可能的递归方程。

And I came up with this equation , not sure if it is right ??? Please help.

T(n) = 2*T(n-1) + c * logn

【问题讨论】:

确切的问题是什么?你想证明某个 c > 1 的 T_f(x) = Theta(c^x) 吗?或者你想要一个精确的公式? g也一样? 这段代码很混乱,我们需要同时考虑函数f(x)和g(x)... 您需要求解 g(x) = 2g(x - 1) - g((x - 1) / 2) + g(x / 2),然后将其重新插入 f(x) 以求解 f(x)。 @nhahtdh 你是从哪里得到这个等式的? @sidstuff: 获胜者是......? Knoothe 先生给出了最严格的界限,他的回答值得被接受,i.m.o,尽管我同意 Saeed 的观点,即 2^n 和 3^n 之间没有太大的实际区别。请不要告诉我们你的老师(这是家庭作业,不是吗?)说 O(n) 是答案(虽然......然后我赢了:-) 顺便说一句:我喜欢这个问题和讨论,先生们! 【参考方案1】:

好的,我想我已经能够证明f(x) = Theta(2^x)(注意时间复杂度是一样的)。这也证明g(x) = Theta(2^x)等于f(x) &gt; g(x) &gt; f(x-1)

首先正如大家所说,很容易证明f(x) = Omega(2^x)

现在我们有了f(x) &lt;= 2 f(x-1) + f(x/2)(因为f(x) &gt; g(x))的关系

我们将证明,对于足够大的x,有一些常数K &gt; 0 使得

f(x) &lt;= K*H(x), where H(x) = (2 + 1/x)^x

这意味着f(x) = Theta(2^x),作为H(x) = Theta(2^x),它本身是由H(x)/2^x -&gt; sqrt(e) as x-&gt; infinity(wolfram alpha链接的限制)这一事实得出的。

现在(警告:较重的数学,也许 cs.stackexchange 或 math.stackexchange 更适合)

根据wolfram alpha(点击链接查看x = infinity附近的级数展开),

H(x) = exp(x ln(2) + 1/2 + O(1/x))

再一次,根据wolfram alpha(点击链接(与上面不同)并查看 x = infinity 的级数展开式),我们有这个

H(x) - 2H(x-1) = [1/2x + O(1/x^2)]exp(x ln(2) + 1/2 + O(1/x))

等等

[H(x) - 2H(x-1)]/H(x/2) -&gt; infinity as x -&gt; infinity

因此,对于足够大的x(比如x &gt; L),我们有不等式

H(x) &gt;= 2H(x-1) + H(x/2)

现在有一些K(仅依赖于L(例如K = f(2L)))这样

f(x) &lt;= K*H(x) for all x &lt;= 2L

现在我们通过(强)归纳法(如果您愿意,可以恢复为自然数)

f(x+1) &lt;= 2f(x) + f((x+1)/2)

通过归纳,右边是

&lt;= 2*K*H(x) + K*H((x+1)/2)

我们之前已经证明了这一点

2*H(x) + H((x+1)/2) &lt;= H(x+1)

因此f(x+1) &lt;= K * H(x+1)

【讨论】:

@Saeed 加油!我们所有的证明都使用相同的递归 H(n) = 2H(n-1) + H(n/2) (我什至计算了加法,作为一个非常注重成本的荷兰人......)你和我都差强人意证明 O(2^n)。 Knoothes 聪明的想法是使用系列 (2+1/n)^n 显然(在擦亮我的眼镜之后:-) 在 O(2^n) (2+ε)^n 使用 fixed epsilon,不会得到 O(2^n)。 (2+1/n)^n 使用 递减 epsilon,并得到结果。 @SaeedAmiri:顺便说一句,这个证明的核心是H(x) &gt;= 2H(x-1) + H(x/2)(这是最困难的部分)。我刚刚看到对您的回答进行了编辑,但仍在挥手。你不能像那样用 1/n 替换 epsilon !您正在跳过证明中最难的部分。如果您不同意,您是否会考虑在 math.stackexchange 上发帖以获得专家级 cmets? 你基本上是在那儿挥手。 @SaeedAmiri:第一个错误无关紧要,因为您似乎只使用 if to f(n) &lt;= 2f(n-1) + f(n/2),这很容易看到(例如,请参阅我的答案)。很明显,重点是找到一个上限(因为下限是微不足道的)。对于 c > 2(即本质上是 (2+epsilon)^n),证明 c^x 的上界容易。困难的部分是提出一个上限,它本身就是 O(2^x)。您的答案完全缺乏这一点,并且您当前的方法不起作用(这就是 HansLub 说答案不足时的意思)。【参考方案2】:

使用memoisation,可以在 O(n) 时间内轻松计算这两个函数。但是 程序 至少需要 O(2^n) 时间,因此是计算 f(n)g(n) 的一种非常低效的方法

为了证明程序在最多 O(2+epsilon)^n 时间对于任何epsilon > 0:

令 F(n) 和 G(n) 分别是在计算 f(n) 和 g(n) 时进行的函数调用次数。显然(将添加计为 1 个函数调用):

F(0) = 1; F(n) = F(n-1) + G(n) + 1 G(1) = 1; G(n) = F(n-1) + G(n/2) + 1

那么可以证明:

F 和 G 是单调的 F > G 定义 H(1) = 2; H(n) = 2 * H(n-1) + H(n/2) + 1 显然,H > F 对于所有 n,H(n) > 2 * H(n-1) 因此 H(n/2) / H(n-1) -> 0 表示足够大的 n 因此 H(n) 0 且足够大的 n 因此对于任何 epsilon > 0 的 O((2 + epsilon)^n) 中的 H (编辑:最初我在这里得出的结论是上限是 O(2^n)。这是不正确的,正如 nhahtdh 指出的那样,但见下文) 所以这是我能证明的最好的......因为 G 0,它们也在 O((2 + epsilon)^n) 中

后记(在看到 Knoothes 先生的解决方案之后):因为 i.m.h.o 一个好的数学证明可以提供洞察力,而不是大量的公式,并且所有这些后代都存在 SO(嗨,女士们!):

对于许多算法,计算 f(n+1) 涉及两倍(三次,..)f(n) 的工作量,加上更多。如果随着 n 的增加(通常是这种情况),使用像上面这样的固定 epsilon 会变得相对更少,这不是最佳的。 用 n 的某个递减函数 ε(n) 替换上面的 epsilon 在许多情况下(如果 ε 下降得足够快,例如 ε(n)=1/n)会产生一个上限 O((2 + ε(n))^ n ) = O(2^n)

【讨论】:

2^n 是下限,所以你应该说它是 Omega(2^n)。 证明的步骤看起来如此挥手,让我脊背发凉...... 但这不是你下沉证明的方式。哪一步失败了,为什么? hence H in O((2 + epsilon)^n) for any epsilon &gt; 0 hence H in O(2^n) 这一步看起来有点可疑。由于 2 + epsilon > 2,当 n --> Inf 时不会 lim (2 + epsilon)^n / 2^n --> Inf?那么 H 不在 O(2^n) 中。 如果有一个反例就更好了:(2^n) * log(n) 对于任何大于 0 的 epsilon 都在 O((2 + epsilon)^n) 中,但不在 O(2^n) 中.所以我的证明是不正确的。【参考方案3】:

令 f(0)=0 且 g(0)=0

从我们拥有的功能来看,

f(x) = f(x - 1) + g(x) 
g(x) = f(x - 1) + g(x/2)

将 g(x) 代入 f(x) 我们得到,

f(x) = f(x-1) + f(x -1) + g(x/2)

∴f(x) = 2f(x-1) + g(x/2)

我们得到扩展,

f(x) = 2f(x-1)+f(x/2-1)+f(x/4-1)+ ... + f(1)

设 s(x) 为如下定义的函数,

s(x) = 2s(x-1)

现在显然 f(x)=Ω(s(x))。

s(x)的复杂度是O(2x)。

因此函数 f(x)=Ω(2x)。

【讨论】:

下界很清楚。更有趣的方面是上限。 -1:因为没有证明任何不平凡的事情,以及以后的错误陈述。 @Deepu:感谢您的收听,但是(不要粗鲁),我真的不认为这个答案值得它得到的支持。您所展示的只是 f(x) = Omega(2^x),这很容易展示。困难的部分是证明 f(x) = O(2^x)。 (nhahtdh 也评论了相同的行)。因此,反对票成立。对于那个很抱歉。顺便说一句,只需 s(x) = 2s(x-1) 就足够了,不是吗?为什么要加 c?【参考方案4】:

我认为很清楚 f(n) > 2n,因为 f(n) > h(n) = 2h(n-1) = 2n支持>.

现在我声称对于每个 n,都有一个 ε 使得: f(n) n,要看到这一点,让我们通过归纳来做,但首先为了更合理,我将使用 ε​​ = 1、显示f(n) n,那我就扩展一下。

我们将使用强归纳,假设对于每个 m m 那么我们有:

f(n) = 2[f(n-1) + f(n/2 -1) + f(n/4 -1)+ ... +f(1-1)]

但对于这部分:

A = f(n/2 -1) + f(n/4 -1)+ ... +f(1-1)

我们有:

f(n/2) = 2[f(n/2 -1) + f(n/4 -1)+ ... +f(1-1]) ==>

A <= f(n/2)   [1]

所以我们可以重写 f(n):

f(n) = 2f(n-1) + A < 2f(n-1) +f(n/2),

现在回到我们的主张:

f(n) < 2*3^(n-1) + 2*3^(n/2)==>
f(n) < 2*3^(n-1) + 3^(n-1) ==>
f(n) < 3^n.  [2]

通过[2],完成了f(n)&in;O(3n)的证明。

但是如果你想把这个扩展成(2+ε)n的格式,只要用1来代替不等式,那么我们就有

对于 ε > 1/(2+ε)n/2-1 → f(n) n.[3]

也可以通过 [3] 说,对于每个 n 都有一个 ε,使得 f(n) n 实际上存在常数 ε,因此对于 n > n0,f(n)&in;O((2+ε)n)。 [4]

现在我们可以像@Knoothe 一样使用wolfarmalpha,通过设置ε=1/n,那么我们将有:

f(n) n 得到 f(n) n,并且我们的简单下限为开始我们有: f(n)&in; Θ(2^n).[5]

PS:我没有准确计算epsilon,但是你可以简单地用笔和纸来计算,我认为这个epsilon不正确,但很容易找到它,如果很难告诉我很难,我会写的。

【讨论】:

是的,您的最后结论不仅适用于 一些 epsilon,而且适用于 every epsilon > 0 @HansLub,在 O 表示法中,当我们说每个 n > n0 时,意味着 n0 是常数,如果你看一下 epsilon 和 n0 之间的关系,epsilon 依赖于 n0,所以我不能说每个 epsilon,因为 n0 是固定的,所以我应该关注 n0 而不是 epsilon,而不是说对于任何 epsilon 都存在 n0,我应该说对于每个固定的 n0 都存在 epsilon 这样......,并且重点是这个,我们应该找到 n0 的 epsilon。 当你说 f 在 O(g) 中时,你不需要提到 n0;您已经声明存在 c 和 n0,使得 f(n) n0。正如你所说,不仅对于任何 n0 存在一个 epsilon,而且对于任何 epsilon 都存在一个 n0 使得 .... 因此对于任何 epsilon,f 在 O((2+epsilon)^n) @HansLub,实际上我不同意所有的 epsilon 都存在 n0 这样......,因为当 epsilon 无限小时,n0 将无限大,然后 n0 不是固定常数。 @HansLub:我现在可以自信地说,这里的答案有问题。 f(x) = w(2^x) 不对。事实上,f(x) = Theta(2^x)!请看我的答案与证明。 (当然,错误可能在我的证明中,但我没有在任何地方挥手,每一步都很容易验证)

以上是关于使用递归方程的程序的时间复杂度的主要内容,如果未能解决你的问题,请参考以下文章

将以下递归算法的时间复杂度 T(n) 表示为递归方程:

递归方程的求解和算法时间复杂度的分析

算法复杂度,求解递归方程

3.4.3递归算法的效率分析

递归函数的时间复杂度分析

(算法专题)使用常微分方程将递归转换为非递归