【问题标题】:Calculating the Recurrence Relation T(n) = sqrt(n * T(sqrt(n)) + n)计算递归关系 T(n) = sqrt(n * T(sqrt(n)) + n)
【发布时间】:2020-07-30 09:44:36
【问题描述】:

我认为这个递归的复杂度是 O(n^2/3)`,通过改变变量和归纳。但我不确定。这个解决方案正确吗?

【问题讨论】:

    标签: algorithm recursion math time-complexity complexity-theory


    【解决方案1】:

    这是一个引人入胜的递归,它确实没有解出 Θ(n)。相反,它似乎解决了 Θ(n2/3)

    为了直观说明为什么这不可能是 Θ(n),让我们假设我们正在处理一个非常非常大的 n 值。那么由于

    T(n) = (nT(√n) + n)1/2

    假设 T(√n) ≈ √n,我们会得到这个

    T(n) = (n√n + n)1/2

    = (n3/2 + n)1/2

    ≈n3/4.

    换句话说,假设 T(n) = Θ(n) 随着 n 变大,我们会得到一个不同的 T(n) 值。

    另一方面,我们假设 T(n) = Θ(n2/3)。然后同样的计算告诉我们

    T(n) = (nT(n) + n)1/2

    = (n·n2/3 + n)1/2

    &大约; (n4/3)1/2

    = n2/3,

    与自身一致。

    为了验证这一点,我编写了一个简短的程序,在给定不同输入的情况下打印出不同的 T(n) 值并绘制结果。这是我写的 T(n) 的版本:

    double T(double n) {
      if (n <= 2) return n;
      return sqrt(n * T(sqrt(n)) + n);
    }
    

    我决定使用 2 作为基本情况,因为反复取平方根永远不会让 n 下降到 1。我还决定使用实值参数而不是离散整数值,只是为了使数学更容易。

    如果你绘制 T(n) 的值,你会得到这条曲线:

    .

    这看起来不像我对线性图的期望。为了弄清楚这是什么,我将它绘制在对数/对数图上,它具有一个很好的特性,即所有多项式函数都转换为斜率等于指数的直线。结果如下:

    我咨询了我的 Handy Neighborhood Regression Software 并要求它确定这条线的斜率。以下是它回馈的内容:

    坡度:0.653170918815869

    R2:0.999942627574643

    这是一个非常很好的拟合,0.653 的斜率非常接近 2/3。所以这是更多的经验证据支持递归求解到 Θ(n2/3)。

    现在剩下要做的就是计算数学。我们将使用一系列替换来解决这种重复。

    首先,我一般不太习惯以这种递归方式使用指数的方式使用它们,所以让我们记录双方的日志。 (在整个阐述中,我将使用 lg n 来表示 log2 n)。

    lg T(n) = lg (nT(√n) + n)1/2

    = (1/2) lg (nT(√n) + n)

    = (1/2) lg(T(√n) + 1) + (1/2)lg n

    ≈ (1/2) lg T(√n) + (1/2) lg n

    现在,让我们定义 S(n) = lg T(n)。然后我们有

    S(n) = lg T(n)

    ≈ (1/2) lg T(√ n) + (1/2) lg n

    = (1/2) S(√ n) + (1/2) lg n

    这更容易处理,尽管我们仍然存在每次幂次递减的问题。为了解决这个问题,让我们再做一次替换,这在处理这类表达式时是相当常见的。让我们定义 R(n) = S(2n)。然后我们就有了

    R(n) = S(2n)

    &大约; (1/2)S(√2n) + (1/2) lg 2n

    = (1/2)S(2n/2) + (1/2) n

    = (1/2) R(n / 2) + (1/2) n

    太棒了!现在剩下要做的就是求解 R(n)。

    现在,这里有一个小问题。我们可以立即使用主定理得出 R(n) = Θ(n) 的结论。这样做的问题是,仅仅知道 R(n) = Θ(n) 不会让我们确定 T(n) 是什么。具体来说,假设我们只知道 R(n) = Θ(n)。那么我们可以这么说

    S(n) = S(2lg n) = R(lg n) = Θ(log n)

    得到 S(n) = Θ(log n)。然而,当我们试图根据 S(n) 求解 T(n) 时,我们会遇到困难。具体来说,我们知道

    T(n) = 2S(n) = 2Θ(log n),

    但是我们不能从这个出发去说 T(n) = Θ(n)。原因是 Θ(log n) 中的隐藏系数在这里很重要。具体来说,如果 S(n) = k lg n,那么我们就有了

    2k lg n = 2lg nk = nk,

    所以对数的前导系数最终将确定多项式上的指数。因此,在求解R时,需要确定线性项的准确系数,转化为S的对数项的准确系数。

    让我们回到 R(n),我们知道是

    R(n) & 约; (1/2) R(n/2) + (1/2)n。

    如果我们重复几次,我们会看到这种模式:

    R(n) & 约; (1/2) R(n/2) + (1/2)n

    &大约; (1/2)((1/2) R(n/4) + (1/4)n) + (1/2)n

    &大约; (1/4)R(n/4) + (1/8)n + (1/2)n

    &大约; (1/4)((1/2)R(n/8) + n/8) + (1/8)n + (1/2)n

    &大约; (1/8)R(n/8) + (1/32)n + (1/8)n + (1/2)n。

    模式似乎是,经过 k 次迭代,我们得到了

    R(n) & 约; (1/2k)R(n/2k) + n(1/2 + 1/8 + 1/32 + 1/128 + ... + 1/22k+1)。

    这意味着我们应该查看总和

    (1/2) + (1/8) + (1/32) + (1/128) + ...

    这是

    (1/2)(1 + 1/4 + 1/16 + 1/64 + ... )

    作为几何级数之和,求解为

    (1/2)(4/3)

    = 2/3

    嘿,看!这是我们之前所说的2/3。这意味着对于取决于递归基本情况的某个常数 c,R(n) 的结果约为 (2/3)n + c。因此,我们看到

    T(n) = 2S(n)

    = 2S(2lg n)

    = 2R(lg n)

    &大约; 2(2/3)lg n + c

    = 2lg n2/3 + c

    = 2c 2lg n2/3

    = 2c n2/3

    = Θ(n2/3)

    这与之前的理论预测值和经验观察值相匹配。

    这是一个非常有趣的问题,我承认我对答案感到惊讶!不过,我有点紧张,因为我可能在出发时错过了一些东西

    lg T(n) = (1/2) lg (T(√n) + 1) + (1/2) lg n

    lg T(n) & 约; (1/2) lg T(√ n) + (1/2) lg n。

    这个 +1 术语实际上可能在我不认识的循环中引入了一些其他术语。例如,是否会产生一个 O(log log n) 项? That wouldn't surprise me,假设我们有一个以平方根缩小的递归。但是,我已经进行了一些简单的数据探索,但我没有看到任何看起来涉及双对数的术语。

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:
      T(n) = sqrt(n*T(sqrt(n)) + n)
      

      我们将双方都提高到 2 的幂:

      [T(n)]^2 = n*T(sqrt(n)) + n
      

      n从两边分开:

      {[T(n)]^2 / n} = T(sqrt(n) + 1 
      

      m 等于log(n) 因此,n 将等于2^m

      {[T(2^m)]^2 / 2^m} = T(sqrt(2^m) + 1
      

      我们将定义一个新函数S(m) = {[T(2^m)]^2 / 2^m}

      S(m) = T(m/2) + 1
      

      根据 Mater 定理等于 θ(log(m)) = θ(log(log(n)))
      所以我们知道:

      {[T(n)]^2 / n} = θ(log(log(n)))
      

      两边乘以n得到:

      [T(n)]^2] = θ(n*log(log(n)))
      

      因此,

      T(n) = θ(sqrt(n*log(log(n))))
      

      【讨论】:

      • 我相信你这里有一些数学错误导致不正确的答案首先,当你除以 n 时,你应该以 T(n)/n = T(sqrt(n)) 结束+ 1,而不是 T(n)/n = T(sqrt(n)) + n。其次,您的递归关系与 S 与 T 而不是 S 与 S 相关,因此您不能将主定理应用于您在此处显示的内容。最后,主定理不适用于您展示的递归类型,因为主定理不处理指数函数。
      • @templatetypedef 准确
      【解决方案3】:

      我们知道:

      T(n) = sqrt(n) * sqrt(T(sqrt(n)) + 1)
      

      因此:

      T(n) < sqrt(n) * sqrt(T(sqrt(n)) + T(sqrt(n)))
      

      1T(sqrt(n)) 替换。所以,

      T(n) < sqrt(2) * sqrt(n) * sqrt(T(sqrt(n))
      

      现在,要找到一个上限,我们需要解决以下循环关系:

      G(n) = sqrt(2n) * sqrt(G(sqrt(n))
      

      为了解决这个问题,我们需要扩展它(假设n = 2^{2^k}T(1) = 1):

      G(n) = (2n)^{1/2} * (2n)^{1/8} * (2n)^{1/32} * ... * (2n)^(1/2^k) => 
      G(n) = (2n)^{1/2 + 1/8 + 1/32 + ... + 1/2^k} = 
      

      如果我们从1/2 + 1/8 + 1/32 + ... + 1/2^k 中取一个因子1/2,我们将得到1/2 * (1 + 1/4 + 1/8 + ... + 1/2^{k-1})。 正如我们所知,1 + 1/4 + 1/8 + ... + 1/2^{k-1} 是一个几何级数,其比率为1/4,它在无穷远处等于4/3。因此G(n) = Theta(n^{2/3})T(n) = O(n^{2/3})

      请注意,作为sqrt(n) * sqrt(T(sqrt(n)) &lt; T(n),我们可以显示类似于前面T(n) = Omega(n^{2/3}) 的情况。这意味着T(n) = Theta(n^{2/3})

      【讨论】:

      • 我想你可能有一个小而重要的数学错误。具体来说,在迭代递归时,我认为您考虑了平方根之一(T(sqrt(n)) 中的一个),但没有考虑另一个平方根(外部 sqrt(n))。这导致你在这里的几何级数衰减为 1/2 + 1/8 + 1/32 + 1/128 + ...,总和为 2/3 而不是 1。我进行了一些实验,看起来确实如此n^{2/3} 是这里的正确答案,而不是 n。
      • @templatetypedef 对。感谢您的评论。
      猜你喜欢
      • 1970-01-01
      • 2017-10-10
      • 2013-08-08
      • 1970-01-01
      • 2016-04-23
      • 2014-12-06
      • 1970-01-01
      • 2015-08-29
      相关资源
      最近更新 更多