【问题标题】:Worst case Analysis On a loop循环上的最坏情况分析
【发布时间】:2014-06-05 16:51:00
【问题描述】:

所以我编写了这个循环,但我无法分析其最坏情况的时间复杂度。任何帮助将不胜感激。

factor 是任意数字 primeNumber 是介于 2 和因子原始值之间的素数列表

for (int i = 0; i < primeNumbers.size() - 1; i++) {
    prime = primeNumbers.get(i);
    if(prime<=factor) {
        if (factor % prime == 0) {
            factor = factor / prime;
            divisors.add(prime);
            i = 0;
        }
        if (factor <= 3) 
            break;
    }
    else 
        break;
}

【问题讨论】:

  • 什么是factor,它在哪里定义?
  • 好吧,假设primeNumbers 的任意大小为n,它最多可以运行多少次
  • 是的,刚刚对其进行了修改并添加了更多信息,是的,我正在尝试查看它最多可以运行多少次
  • 它最多运行 (primeNumbers.size() - 1) 次。这意味着它是 O(n)。
  • 说真的......你最糟糕的情况是primeNumbers 中的每个元素都小于factor,所以它是 O(N)。另外,由于您不会更改primeNumbers 的状态,因此最好使用增强的for 循环,因为某些列表可能会遍历List#get 中的整个列表,或者使用Iterator

标签: java time complexity-theory analysis


【解决方案1】:

最坏的情况: 因子是素数。
所以我们永远不会到达break 指令。
循环体将被执行primeNumbers.size() 次。

现在我们应该评估primeNumbers.size()
这是number of prime numbers below a given number = O(n/ln n)

让我们证明使用if (factor % prime == 0) 语句会减少计算次数。
如果我们到达那里,那将意味着factor = p*m.
所以我们会得到O(p/ln(p) + m/ln(m)) = O((p*ln(m) + m/ln(p))/(ln(m)*ln(p))) O((p*m)/(ln(m)*ln(p))) O((p*m)/(ln(m) + ln(p))) = O(p*m/ln(m*p)) = O(n/ln n)
因此,以这种方式划分我们减少了计算次数。

【讨论】:

  • 您是否考虑过如果 factor%prime==0 我们将计数器重置为 0 并重新启动,尽管使用不同的因素
  • 好点。只是直觉,除法只会减少计算量。我为这个案例添加了正式证明。
  • 哇哦,你真的很擅长这个......哈哈,现在对我来说很有意义,非常感谢尼古拉
【解决方案2】:

Nikolay 的回答对您提出的问题给出了最直接的回答,该问题专门针对除法运算次数方面的性能复杂性,假设每个除法运算都有统一的成本。但是有两个观察结果:

1) 您可以通过在 prime^2 > 因子时停止循环来显着提高此测试的性能。这样做的原因是,如果在因子的平方根之下找不到除数,那么在平方根之上也找不到除数。通过此修改,您将获得更新的性能 O(sqrt(n)/ln(sqrt(n))) = O(sqrt(n)/(sqrt(n)/2)) = O(sqrt(n) /ln(n))。

2) 当数字变得足够大到“有趣”时(即,不能仅仅放入 64 位整数,但可以任意大的数字),您的方法将面临一个有趣的问题:查找第 n 个项目的操作将会增加,因为在当今大多数当前硬件上,您可能会面临所有素数的内存管理问题。您可能仍然可以接受所有可以放入 32 位整数的素数,从而发现小于 64 位的所有整数的因子,但除此之外,您的方法将面临明显的麻烦。在任何情况下,一旦超过 64 位并开始寻找任意大整数的因子(例如 Java BigInteger),即使您可以管理内存,也需要更新性能分析以考虑您实际使用的整数的大小正在考虑。 Nikolay 的分析很好,假设每个部门都有统一的成本。但是,如果您开始使用更大数量的表示,那么统一成本的假设就会被打破。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-09-23
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    • 2019-07-06
    • 2015-06-09
    相关资源
    最近更新 更多