【问题标题】:complexity of foo algorithmfoo算法的复杂度
【发布时间】:2011-06-21 15:00:18
【问题描述】:

我有这个无法解决的问题.. 这个 foo 算法的复杂度是多少?

int foo(char A[], int n, int m){
  int i, a=0;
  if (n>=m)
    return 0;
  for(i=n;i<m;i++)
    a+=A[i]  
  return a + foo(A, n*2, m/2);
}

foo 函数被调用:

foo(A,1,strlen(A));

所以.. 我猜它是 log(n) * 内部 for 循环的东西.. 我不确定它是 log(n) 还是什么..

可能是 log^2(n) 的 theta 吗?

【问题讨论】:

  • 不,这是我今天完成的考试,我想了解我是否做对了(我怀疑..)拜托,也许在这里问不是特别合适,但我在 cstheory.stackexchange 上问过,他们说我应该在这里问。
  • 我不认为从功课中提问有问题,这只是礼仪(我相信)很清楚地表明它是
  • 依赖大小写敏感是不好的(aA 都被定义了),因为这会降低代码的可读性、代码搜索结果的相关性等……此外,m 的值应该在函数本身内部计算以进行 DRY 编码。然后,您正在除一个整数,而您不知道它的值。除此之外,假设这是 C,a+=A[i] 行上存在语法错误。最后但同样重要的是,第一次没有检查nm 的值的大小,所以当m 很大而n 很小时,很容易发生堆栈溢出。错误的代码。不敢相信这出现在考试中。
  • 啊哈!你说得对!与其他人相比,这是相当不错的......仍然是我们所拥有的......

标签: algorithm computer-science complexity-theory


【解决方案1】:

我不确定是否有“快速而肮脏”的方法,但您可以使用旧的好数学。没有花哨的定理,只有简单的方程式。

在第 k 层递归(k 从零开始),循环将有~ n/(2^k) - 2^k 迭代。因此,对于0 &lt;= i &lt;= l,循环迭代的总次数将是S = sum(n/2^i) - sum(2^i),其中l是递归的深度。

l 大约是log(2, n)/2(证明这一点)。

将公式中的每个部分分别转换为S,我们得到。

S = (1 + 2 + .. + 2^l)*n/2^l - (2^(l + 1) - 1) ~= 2*n - 2^(l + 1) ~= 2*n - sqrt(n)

由于除了循环之外的其他语句只会重复l 次,我们知道l ~= log(2, n),它不会影响复杂性。

所以,最后我们得到O(n)

【讨论】:

    【解决方案2】:

    这是主定理的一个很好的应用:

    根据 n 和 X = m-n 重写:

    int foo(char A[], int n, int X){
      int i, a=0;
      if (X < 0) return 0;
      for(i=0;i<X;i++)
        a+=A[i+n]  
      return a + foo(A, n*2, (X-3n)/2);
    }
    

    所以复杂度是

    T(X, n) = X + T((X - 3n)/2, n*2)
    

    注意到惩罚随着X增加而随着n减少,

    T(X, n) < X + T(X/2, n)
    

    所以我们可以考虑复杂性

    U(X) = X + U(X/2)
    

    并将其代入主定理以求 U(X) = O(X) --> 复杂度为 O(m-n)

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-22
    • 1970-01-01
    • 2013-11-01
    • 2016-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多