📜  算法样本问题复发|套装2

📅  最后修改于: 2021-04-29 06:43:18             🧑  作者: Mango

  • 问题1: T(n)的复杂度是多少?

    T(n) = T(n-1) +  \frac{1}{n(n-1)}

    1. Θ( 1n )
    2. Θ( 1n 2 )
    3. Θ(1)
    4. Θ(ln(n))

    答:3
    说明:使用替换技术来求解给定的递归函数,可以归纳地猜测T(n)的闭合形式(非递归形式),如下所示:

    T(n) = T(1) +  \sum_{k=1}^{n} \frac{1}{k(k-1)}

    在继续进行并涉及复杂的分数之前,最好简化手头的方程式。部分分数分解法是一种常用的表示有理分数的方法,其中分子和分母都是多项式形式,是一个或几个分数和一个较简单分母的总和。使用此方法可以得到:

     \frac{1}{k(k-1)} = \frac{A}{K} + \frac{B}{k-1}

    进行分解时,A和B的值分别为-1和+1。执行此分解后,T(n)的非递归形式应写为:

     T(n) = T(1) +  \sum_{k=1}^{n} (\frac{1}{k-1} - \frac{1}{k})

    扩展T(n)的这种紧凑表示将导致:

     T(n)=T(1)+((\frac{1}{1}-\frac{1}{2})+(\frac{1}{2}-\frac{1}{3})+...

    +(\frac{1}{n-2}-\frac{1}{n-1})+(\frac{1}{n-1}+\frac{1}{n}))

    显而易见的是,除第一个和最后一个分数外,每个分数均出现两次,但每次符号相反。因此,除第一个和最后一个分数外,所有分数都将消失:

    T(n) = T(1) + \frac{1}{1} - \frac{1}{n} = T(1) + 1 - \frac{1}{n}

    从刚刚得出的最后一个方程,T(n)的渐近复杂度为:

     T(n) \in \theta (1 - \frac{1}{n}) \in \theta (1)

  • 问题2:确定(计数)具有四个偶数个“ a”的字符{a,b,c,d}的长度为N的字符串的总数吗? [C(N)是函数Count(N)的缩写,用于此目的。]
    1. C(N)= 5.0 * 3 N-1 – 1.0 * 5 N-1
    2. C(N)= 1.0 * 4 N + 6
    3. C(N)= 0.5 * 2 N + 0.5 * 4 N
    4. C(N)= 1.0 * 2 N + 2.0 *(3) N
    Example: 
    
    For n = 1, there are 3 distinct strings: C(3) = 3
    
    • b,c,d。

    对于n = 2,r,对于n = 2,10个可能的字符串是:C(10)= 10

    • aa,bb,cc,dd,bc,bd,cb,cd,db,dc

    答:3
    说明:在给定约束的情况下,字符串的第一个字符有两种可能的情况:

    1. 除“ a”外,第一个字符可以是可能的字符“ b”,“ c”或“ d”之一。在这种情况下,目的是找到由偶数个“ a”构成的剩余长度为“ N-1”的字符串的数目。
      • C(N)= 3 * C(N-1)
    2. 第一个字符可能是“ a”,而“ a”中的一个已经出现;因此,应该计算奇数为“ a”的可能字符串的数量。此数字不能称为C(N-1),但仍可以通过使用C(N-1)来实现C(n)。
      • C(N)= 4 N-1 – C(N-1),其中:
        • 4 N-1 :四个字符的长度为(N-1)的可能字符串的总数
        • C(N-1):长度为(N-1)的字符串由偶数个“ a”组成。

    由于上述两种不同的情况不能同时发生,因此字符串的总数是这些情况的总和:

     C(N) = 3 * C(N-1) + (4^{N-1} - C(N-1))

     = 2*C(N-1) + 4^{N-1}

    需要以下两个初始条件来找到特定的解决方案:

    1. 对于n = 1,存在3个不同的字符串:b,c,d。
    2. 或者,对于n = 2,10个可能的字符串是:aa,bb,cc,dd,bc,bd,cb,cd,db,dc

    现在,问题可以表述为:

     C(N) = C_{1} * 2^{N} + C_{2} * 4^{N}, C(1) = 3, C(2) = 10

    具有给定约束的字符串总数为:

    C(N) = 0.5  * 2^{N} + 0.5 * 4^{N}

  • 问题3:哪个递归函数没有多项式形式的解?
    1.  T(N) = 2 * T(n-2) + 1
    2.  T(N) = T(n-1) + N^{2}
    3.  T(N) = T([ \frac{8}{9} n ] ) + 9 * n + 1
    4.  T(N) = 100 * T(\frac{n}{99}) + N

    答:1
    说明:需要上述所有方程式的解才能看到选项不是多项式的解。可以看出,所有的解都是多项式形式的,除了第一种选择。以下是对这些选项的分析:

    1. 选项(1)具有指数解:为了找到第一个选项中给出的方程的齐次解,需要其特征方程的根:

       T(N) = 2 * T(n-1) + 1  \Rightarrow r^{2} - 2 = 0   \Rightarrow r =  \pm  \sqrt{2}

      因此,该解决方案具有指数形式:

       T(n)= c_{1} *( \sqrt{2})^{n}+ c_{2}*(-\sqrt{2})^{n}

       = c_{1} *2^{n/2}+c_{2} *(-1)^{n} * (2)^{n/2}

    2. 选项(2):第二种选择的方程式可以通过替换技术轻松解决:

       T(n) = T(n-1) + n^{2} = T(n-2) + n^{2} + (n-1)^{2}

      可以归纳地猜出的T(n)的闭合形式为:

       T(n) = T(1) + \sum_{k=1}^{n} k^{2}

      = T(1) + sum.of.square.numbers  \approx  \frac{n(n+1)(2n+1)}{6}

      这就是说它是一个三阶多项式函数(三次多项式):

       T(n) \in  \theta (T(1)) + \theta ( n^{3} ) \in \theta (1) + \theta (n^{3}) \in \theta (n^{3})

    3. 选项(3):根据主定理,在第三个选项中提出的方程的复杂度为 \theta(n)
    4. 选项(4):第四选择方程式属于主定理的情况3;因此它的复杂性是 \theta(n^{\frac{100}{99}})
  • 问题4:哪一个可以最好地估计F(n)渐近复杂度?

     F(n) =\begin{cases}{F(\frac{n}{2}) + n^{3}} & {n  \leq 100}\\{F(100) + n^{2}} & {n>100}\end{cases}

    1. O(n 3 )
    2. Ω(n 2 )
    3. O(n 2 )
    4. Θ(n 2 )

    答:4
    说明:在对这些问题做出任何决定之前,需要考虑一些棘手的事实:

    1. [找到尽可能紧密的边界]最佳渐近估计是当复杂性行为用Θ表示法表示时。这主要是基于算法的平均性能,即所谓的“平均情况”场景,该场景需要进行复杂的分析,程序员更喜欢使用O()之类的其他符号。但是,尝试找到最紧密的边界仍然是一个好习惯。
    2. [符号表示无穷大]数学渐近符号表示无穷大时复杂函数的行为,或者当“ n”趋向于非常大时。无限是一个假想的抽象概念,在现实生活中无法实现。为了进行计算并了解函数行为,应考虑的数量仅取决于问题。在这种情况下,似乎对输入数据大小“ n”没有限制。
    3. [了解测试人员的陷阱]为了摆脱测试人员提供的潜在陷阱,应将足够大的值分配给n;在此问题中,不应选择较小的值,例如100或1000。由于需要比较n <100时n 3的复杂度与n> 100时n 2的复杂度,因此大于1000的值是可以接受的,这会导致n = 100时n 2 excel n 3 。即使我们要在每个调用时间重新计算F(100),对于n> 1000,n 2始终大于F(100),对于较小的值(例如n = 100),它的n 3阶数。在n> 1000的所需计算中,可以简单地忽略F(100)的值。
    4. [在现实世界的应用中,有时使用一些辅助存储器空间来提高速度有时是有效的]在此问题中,使用Θ(1)的辅助存储空间来保存F( 100)一次以备将来使用,而不必在n> 100的每个调用时间重新计算F(100)。因此,F(100)的复杂度将为O(1),可能只是为了读取一个值,而对于n> 100,F(n)的复杂度将为Θ(n 2 )。

    F(n)的复杂度为:

     F(n) \in \Theta (n^{2})

  • 问题5:哪一个为k和α(alpha)指定合适的范围,以下渐近表达式成立?

     (ln(n))^{k} \in O(n^{ \alpha })

    1. α≥0&k≤α
    2. α≥0.1&k≥0
    3. α> 1&k&in; [R
    4. α> 0&k&in; [R

    答:4
    说明:一个非常可靠的资源(麻省理工学院的一份备忘单)可以有效地解决此问题。但是,并非所有解决方案,而是此解决方案中描述的重要部分,都是基于此MIT备忘单上的推导。

    目的是找到表达式ln k n&in;的范围。 O( )是正确的。可能不保留该表达式的最坏条件是让表达式的左侧变得很大,同时试图迫使右侧保持尽可能小。换句话说,尝试为指数“ k”分配较大的可能值,同时在另一侧为指数“ Alpha”指定非常小的值。甚至可以将小于1的较小值分配给α。但是,目前,α被赋予一个可选的特定常数E,但还没有一个负值。 Α既未设置作为“ n”的函数的变量E(n),因为这将是一个全新的要解决的问题,而不是此问题中描述的问题。

    令α= | E | (可选的小正常数),并且k> 0;目的是查看表达式ln k n&in; O(n E )是否为真:

     \lim_{n \rightarrow  \infty } \frac{ln(n)^{k}}{n^{| E |}} =   (\lim_{n \rightarrow  \infty } \frac{ln(n)}{n^{\frac{| E |}{k}}})^{k} = (\frac{ \infty }{ \infty })^{k}

    应用Hopital规则可得出:

    (\lim_{n \rightarrow  \infty } \frac{ln(n)}{n^{\frac{| E |}{k}}})^{k} = (\lim_{n \rightarrow  \infty } \frac{\frac{1}{n}}{\frac{|E|}{k} * n^{\frac{|E|}{k}}-1})^{k}

     = (\lim_{n \rightarrow  \infty } \frac{\frac{1}{n}}{\frac{|E|}{k} * n^{\frac{| E |}{k}}* \frac{1}{n}})^{k} = (\lim_{n \rightarrow  \infty } \frac{1}{\frac{|E|}{k} * n^{\frac{| E |}{k}} })^{k} = 0

    到目前为止的推论表明,对数函数没有正指数“ k”,即使对很小的正指数,它也可以超过变量“ n”。可以肯定的是,当对数函数取负指数并变得更小时。换句话说:

    (ln(n))^{-|k|}  \leq  (ln(n))^{k} \in O(n^{|E|})

    如果指数Alpha取负值(α=-| E |),该怎么办?由于负指数意味着翻转分数,翻转派系伴随着不等式的改变,因此得出:

    \frac{1}{(ln(n))^{k}}  \geq  \frac{1}{n^{|E|}}

    O标记不再成立。因此,保留上述不等式的范围是k&in;时。 R&α> 0;用数学语言:

     (ln(n))^{k} \in O(n^{\alpha} )为k&in; R&α> 0

    多项式表达式不能包含具有分数指数的变量;因此,由于采用了这样的分数值,因此这个问题甚至更具包容性。结果,此问题陈述描述了多项式表达式比对数函数更容易增长的速度。

    来源:

    1. 麻省理工学院渐近备忘单
    2. 伊朗大学考试的汇编(包括一些摘要,修改和翻译)