【问题标题】:What is the time complexity of this C++ function?这个 C++ 函数的时间复杂度是多少?
【发布时间】:2011-08-07 23:24:09
【问题描述】:

我写了一个函数来显示素数和特定数 n 的因数。

bool PrimeFactor(int n){
    int count = 0;// count divisors

    for (int i = 2 ; i < n; i++){
        if ( n % i == 0 ){
            if ( PrimeFactor(i)){              
                cout << i << endl;
            }
            count ++;
        }
    }

    if (count > 0)//not prime
        return false;
    return true;
}

结果可能会在某些地方重复,但这不是大问题。我不知道如何计算这个递归函数的时间复杂度。

【问题讨论】:

  • 取决于PrimeFactor 的作用。
  • 为什么这个函数是递归的? (顺便说一句,我将你的代码包装成一个名为 PrimeFactor 的函数,因为你说它是递归的。我希望我没看错。)
  • 另外,请注意,此函数将返回 true 为 0 和 1,两者都不是素数。
  • 它是如何终止的?如果PrimeFactor(2) 被调用,那么2 % 2 为零,所以它会一直循环?
  • @Jeff:不,第一次迭代不会满足循环条件。

标签: c++ time-complexity


【解决方案1】:

这种简化的递归次数不会少于原来的次数,并且它具有复杂性O(n!)。所以这是一个上限。

bool PrimeFactor(int n)
{
    for (int i = 2 ; i < n; i++) PrimeFactor(i);
}

我觉得原文的复杂度是O(n log n loglog n ...)

【讨论】:

  • 原件可以是 O(n!) 吗?你能解释一下你的答案吗
  • 必须指定增长的顺序;它不能是递归无限的。此外,我的增长顺序是2 ^ n,它不能是n log n ...探索算法(您的回复中的那个)我得到以下结果:当n = 5时,调用次数为8;当 n = 10 时,调用次数为 256;当 n = 20 时,调用次数为 262144。你能注意到它是指数级的吗?
  • @MohamedEnnahdiElIdrissi:我的主张是问题中版本的顺序小于我的答案中的版本。
【解决方案2】:

这基本上是 Ben Voigt 答案的扩展版本。

正如 Ben Voigt 所说,没有条件的版本是 O(n),这应该很简单。

现在,带有条件的版本将在 if 语句内执行递归的次数等于 n 的除数(= value of the divisor function for n = d(n))。

下限inf d(n) = 2,因为对于每个素数,这都是真的,并且有无限多的素数,所以无论你做多大的n,你总能找到一个d(n) = 2。这意味着对于素数,您的函数将递归 0 次,并且具有复杂性 O(n)

上限更复杂(我需要咖啡),所以让我们暂时跳过它并计算平均复杂度。 d(n) = O(log n) 的平均复杂度,因此,正如 Ben Voigt 所说,原始函数的平均复杂度为 O(n log n loglog n ...)。更详细地说:你有 for 循环,即 O(n),在这个 for 循环中,你将平均递归 d(n) = O(log n) 次。现在你再次进入函数并递归O(log (log n))次等等。

另请注意 DarkDust 和 Jeff Forster 对您的问题的 cmets。它也不会按照您想要的方式运行。此外,检查偶数是否除以n 是没有用的,因为偶数永远不会是素数(当然除了 2)。由于递归,您将在递归调用期间输入内部 if(带有 cout 的那个),因此您得到的输出将不是您想要的(我假设这是 n 的不同主要除数)。

另一种节省时间的方法是只测试floor(sqrt(n))。如果一个数 i 正好整除 n,请检查商 j = n / i 是否也是质数。例如。对于n = 6,您将测试到floor(sqrt(6)) = 2。然后你发现i = 2 是一个除数,你检查j = 6 / 2 = 3。你会发现ij 在这种情况下都是素数。

【讨论】:

  • 很好的解释。我不知道“除数函数”,我只是在猜测(稍微挥动一下,因子相乘得出数字)。很高兴我的估计结果是正确的。当然,仍然有可能(甚至可能)一个数字的除数函数不独立于除数的除数函数值,因此乘法并不严格正确。但它仍然应该是正确的复杂性。
  • 谢谢。那么复杂度能接近 n^2 吗?
  • @silentbang 我想是的,不过不要相信我的话。我一直在寻找lim sup d(n) 的复杂性,但在任何地方都找不到。再说一次,我不是数学家,所以我可能正在寻找错误的东西。或者也许它就在我面前,我看不到它。也许可以尝试在math.stackexchange.com 上提问。
  • @silentbang 这里,问它:math.stackexchange.com/questions/34501/…
【解决方案3】:

我试图以正式的方式翻译(到递归关系)并解决您的算法,如下所示:

增长的顺序是非多项式,这是一个要避免的算法!

【讨论】:

  • 在总和消失的步骤中看起来像是一个错误......我猜你已经取消了大部分条款,但f(n-1, i)f(n, i) 不同,所以取消不正确。 (您在最后一步中有一个额外的错误,它不会影响复杂性,但第一个错误会)
  • 另外,你对f的定义是倒退的。
猜你喜欢
  • 2020-12-03
  • 2017-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
  • 2022-09-22
  • 1970-01-01
相关资源
最近更新 更多