小淼博客

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Question1

计算 T(n)=T(n-1)+3lgn 表达式的时间复杂度,猜测为O(nlgn)

一、直接递归迭代法

1. 迭代推理

T(n) = T(n-1) + 3lg(n)  
     = T(n-2) + 3lg(n-1) + 3lg(n)  
     = T(n-3) + 3lg(n-2) + 3lg(n-1) + 3lg(n)  
     ...  
     = T(1) + 3[lg(2) + lg(3) + ... + lg(n)]

2. 分析lg函数求和问题

lg(2) + lg(3) + ... + lg(n)

这是从2到n的对数的部分和。虽然这个部分和没有闭合形式的表达式,但我们可以使用积分来近似它的行为。总和近似等于lg(x)从2到n的积分,即:

\[\begin{split} ∫_2^n lg(x) dx = [x * lg(x) - x]_2^n \\ &= (n * lg(n) - n) - (2 * lg(2) - 2) \\ &= n * lg(n) - n + 2 - 2 * lg(2) \\ &= n * lg(n) - n + O(1) \end{split} \]

(注:O(1)项表示一个不依赖于n的常数。)

3. 计算最终的时间复杂度

由于对数之和近似为n*lg(n)-n,因此递归关系的总体时间复杂度为:

T(n) = T(1) + 3[n * lg(n) - n + O(1)]  
     = T(1) + 3n * lg(n) - 3n + O(1)

忽略常数项和低阶项(因为我们对渐近行为感兴趣),我们有:

T(n) = O(n * lg(n))

因此,递推关系T(n)=T(n-1)+3lg(n)的时间复杂度为O(n*lg(n))。

要证明一个算法的时间复杂度是\(O(n \log n)\),我们需要使用数学归纳法或者通过直接分析算法的执行过程来展示这一点。对于给定的递推关系\(T(n) = T(n-1) + 3\log n\),我们可以使用递推展开和求和的方法来证明其复杂度。

首先,我们展开递推式的前几项:

\[T(n) = T(n-1) + 3\log n \]

\[T(n-1) = T(n-2) + 3\log(n-1) \]

\[\vdots \]

\[T(2) = T(1) + 3\log 2 \]

将上述所有等式相加,我们得到:

\[T(n) = T(1) + 3[\log n + \log(n-1) + \ldots + \log 2] \]

现在,我们需要考虑对数项的和。对于连续整数的对数之和,没有简单的封闭形式表达式,但我们可以使用积分来近似求和。对于大的\(n\),这个和有如下近似:

\[\log n + \log(n-1) + \ldots + \log 2 \approx \int_{2}^{n} \log x \, dx \]

计算这个积分,我们得到:

\[\int_{2}^{n} \log x \, dx = [x \log x - x]_{2}^{n} = n \log n - n - (2 \log 2 - 2) \]

忽略常数项和较低阶的项(因为它们在确定渐近复杂度时不是主要的),我们得到:

\[T(n) \approx T(1) + 3(n \log n - n) = O(n \log n) \]

这里,我们使用了大O记号的性质,即如果\(f(n) = O(g(n))\)\(h(n)\)是某个正数,那么\(hf(n) = O(g(n))\)。在我们的情况下,\(h(n) = 3\)

因此,我们证明了\(T(n)\)的时间复杂度是\(O(n \log n)\)。注意,这个证明是基于对数求和的近似,对于严格的数学证明,可能需要更精细的分析,包括使用更精确的对数求和的界。然而,上述方法提供了对复杂度的一个直观理解,并且通常用于算法分析的初步阶段。

二、猜测代入验证法

1. 猜测合理的时间复杂度

根据题目提示,可以知道猜测是时间复杂度为 O(nlgn),将当前的时间复杂度代入得到:

使用代入法来解决递归式\(T(n) = T(n-1) + 3\log n\)的时间复杂度问题,我们首先需要假设一个复杂度上界,然后将其代入递归式中,验证是否成立。

首先,我们假设\(T(n) \leq c \cdot n \log n\),其中\(c\)是一个正常数,我们需要找到满足这个不等式的最小的\(c\)

然后,我们将这个假设代入递归式中:

\[T(n) = T(n-1) + 3\log n \leq c \cdot (n-1) \log (n-1) + 3\log n \]

为了简化这个不等式,我们可以使用对数的一些性质,比如\(\log ab = \log a + \log b\)\(\log a^b = b \log a\)。但是,在这个情况下,直接比较项的数量级更为简单。我们知道,对于大的\(n\)\(\log(n-1)\)\(\log n\)是相近的,因此我们可以近似地认为\(\log(n-1) \approx \log n\)

基于这个近似,我们有:

\[c \cdot (n-1) \log (n-1) + 3\log n \approx c \cdot n \log n - c \cdot \log n + 3\log n \]

\[= c \cdot n \log n + (3 - c) \log n \]

为了使得\(T(n) \leq c \cdot n \log n\)成立,我们需要\((3 - c) \log n\)这一项是非正的,即\(3 - c \leq 0\),从而得出\(c \geq 3\)

因此,我们找到了一个满足条件的\(c\),即\(c = 3\)。所以,我们可以得出结论,递归式\(T(n) = T(n-1) + 3\log n\)的时间复杂度上界是\(O(n \log n)\)

需要注意的是,这个上界可能不是紧的,因为我们使用了近似和忽略了一些项。为了得到紧的上界,我们通常需要更精细的分析,比如使用数学归纳法或者更精确的对数求和的界。但是,通过代入法,我们至少得到了一个合理的时间复杂度上界。

为了得到递归式\(T(n) = T(n-1) + 3\log n\)的上界和下界,我们需要分析递归式中每一项的增长情况,并确定其总和的界限。

首先,我们考虑递归式的下界。由于每一项都是非负的(因为对数函数对于正数总是非负的),所以递归式的下界至少是其中的一部分项的和。在这种情况下,最简单的下界是忽略除了最后一项之外的所有项,即:

\[T(n) \geq 3\log n \]

这是因为\(T(n)\)至少包含\(3\log n\)这一项(假设\(T(1)\)是一个常数,不影响渐近分析)。因此,\(O(n\log n)\)\(T(n)\)的一个下界,尽管这不是一个紧的下界,因为它没有考虑到所有项的总和。

接下来,我们考虑上界。为了得到上界,我们需要对递归式中的每一项进行求和。我们已经知道,对于大的\(n\),求和\(\log 2 + \log 3 + \ldots + \log n\)可以近似为\(\int_{2}^{n} \log x \, dx\),其结果为\(n\log n - n + O(1)\)。因此,递归式的总和可以近似为:

\[T(n) \approx T(1) + 3(n\log n - n + O(1)) \]

忽略常数项和较低阶的项,我们得到:

\[T(n) = O(n\log n) \]

这里,\(O(n\log n)\)是递归式的一个上界。注意,这个上界是紧的,因为当我们将所有项加起来时,确实得到了一个与\(n\log n\)成比例的量级。

综上所述,我们得到递归式\(T(n) = T(n-1) + 3\log n\)的下界至少为\(O(\log n)\)(尽管这不是一个紧的下界),而上界为\(O(n\log n)\),并且这个上界是紧的。因此,我们可以说递归式的时间复杂度是\(O(n\log n)\)

Que2

对于递归式\(T(n) = 4T(n/3) + n^2\),我们可以使用主定理(Master Theorem)来求解其时间复杂度。主定理是一种用于解决形如\(T(n) = aT(n/b) + f(n)\)的递归式的时间复杂度的方法。

首先,我们识别递归式中的参数:

  • \(a = 4\)(递归调用的数量)
  • \(b = 3\)(问题规模减小的因子)
  • \(f(n) = n^2\)(非递归部分的复杂度)

接下来,我们计算\(f(n)\)\(n^{\log_b a}\)的渐近比较。这里,\(\log_b a = \log_3 4\)。我们需要确定\(f(n)\)是大于、等于还是小于\(n^{\log_b a}\)

由于\(n^2\)的增长速度明显快于\(n^{\log_3 4}\)(因为\(\log_3 4 < 2\)),我们可以得出结论,\(f(n)\)是较大的那一项。

根据主定理的情况3(当\(f(n)\)是较大的项时),递归式的时间复杂度为\(O(f(n))\)。因此,\(T(n) = O(n^2)\)

所以,递归式\(T(n) = 4T(n/3) + n^2\)的时间复杂度是\(O(n^2)\)

代入法

要确定递归式\(T(n) = 4T(n/3) + n^2\)的上界和下界,我们首先需要理解递归式如何展开,并观察各项的增长情况。

下界确定

对于下界的确定,我们通常需要找到一个比递归式本身更简单但仍然保持相同或更快增长率的表达式。在这个例子中,由于\(n^2\)项的存在,任何小于\(n^2\)的下界都是显然的,但这样的下界可能不够紧。一个更紧的下界可能不容易直接得出,因为它需要考虑到递归调用的累积效应。

然而,如果我们忽略递归调用部分(即\(4T(n/3)\)),那么\(n^2\)本身就是递归式的一个下界,因为\(T(n)\)至少包含这一项。因此,我们可以说\(T(n) \geq n^2\),这是一个显然的下界。但请注意,这不是一个紧的下界,因为递归调用部分也会对总复杂度产生贡献。

上界确定

对于上界的确定,我们可以尝试使用归纳法或者通过展开递归式来观察其增长情况。在这个例子中,我们可以使用递归树的方法来估计上界。

递归树的每一层都代表一次递归调用,而每一层的节点数则是该层递归调用的数量。对于递归式\(T(n) = 4T(n/3) + n^2\),每一层的节点数是前一层的4倍(因为每次递归调用自身4次),而每个节点的计算量是\(n^2\)(因为每次递归调用都加上一个\(n^2\)项)。

如果我们忽略递归调用的重叠部分(即假设每次递归调用都是完全独立的),那么我们可以将每一层的计算量相加来得到一个上界。每一层的计算量是一个等比数列,首项是\(n^2\),公比是\(4/9\)(因为每次递归调用时\(n\)变为\(n/3\),所以\(n^2\)变为\((n/3)^2 = n^2/9\),而递归调用的数量是4倍)。

这个等比数列的和可以计算为:

\[\sum_{i=0}^{\log_3 n - 1} 4^i \left(\frac{n}{3}\right)^{2i} = n^2 \sum_{i=0}^{\log_3 n - 1} \left(\frac{4}{9}\right)^i \]

由于\(\sum_{i=0}^{\infty} (\frac{4}{9})^i\)是一个收敛的几何级数,其和为\(\frac{1}{1 - \frac{4}{9}} = \frac{9}{5}\),因此上界可以近似为:

\[T(n) \leq \frac{9}{5} n^2 \log_3 n \]

这里我们使用了\(\log_3 n\)来近似递归树的深度,因为每次递归调用\(n\)都会除以3。

需要注意的是,这个上界可能不是紧的,因为它假设了每次递归调用都是完全独立的,而实际上递归调用之间存在重叠。为了得到更紧的上界,可能需要使用更复杂的分析技术,比如主定理(Master Theorem)或者更精细的递归树分析。

综上所述,我们可以说递归式\(T(n) = 4T(n/3) + n^2\)的下界至少是\(n^2\),而上界可以通过递归树分析等方法来估计。在实际应用中,我们通常会尝试找到紧的上界和下界,以更准确地描述算法的时间复杂度。

算法复杂度绘图

posted on 2024-04-12 22:25  小淼博客  阅读(0)  评论(0)    收藏  举报

大家转载请注明出处!谢谢! 在这里要感谢GISPALAB实验室的各位老师和学长学姐的帮助!谢谢~