“if”语句是否会影响时间复杂度分析?

时间:2012-09-01 21:19:21

标签: java algorithm complexity-theory

根据我的分析,这个算法的运行时间应该是N 2 ,因为每个循环都会遍历所有元素。我不确定if语句的存在是否会改变时间复杂度?

for(int i=0; i<N; i++){
    for(int j=1; j<N; j++){

        System.out.println("Yayyyy");
        if(i<=j){
            System.out.println("Yayyy not");
        }
    }
}

6 个答案:

答案 0 :(得分:6)

  • Tp :将常量文本打印到标准输出所需的时间。
  • Ti :内循环内所有其他操作所需的时间(谓词评估等)。
  • To :除了执行内部循环(初始化计数器等)之外,外部循环内所有操作所需的时间。
  • Tc :设置流程和其他所有簿记所需的时间

总运行时间 Tc + N x(To + NxTi + N / 2xTp)

这等于 Tc + NxTo +(Nx(N / 2))x(2Ti + Tp),其由 K x(N ^ 2)界定对于 K>的值Ti + Tp / 2 N 变为无穷大。这个边界使得时间复杂度仍然 O(N ^ 2)

不, if 语句不会改变此示例中的时间复杂度。

答案 1 :(得分:3)

没有。考虑时间复杂度渐近地描述时间 - 我们将较低的时间复杂性吸收到更高的时间。

O(n²)表示k × n² + c,假设c非常低,我们不关心它。

这些是常数效应,整个事物(c)的一定开销和每个复杂性的一定数量的成本。如果算法具有较低的,或者如果它们相等,则k算法会低于c算法。另外,对于足够低的n值,O(n²)与O(1)相同(我们通常不会关心,但每个的k可能会大不相同,而且如果我们每个都做然后,当O(n²m)击败O(m)时,如果n很低,那不是真正比较的那些)..

无论如何,这是一种刻意的过度简化,因为kc可能不是真正的常数,就像常数一样好。因此,如果某事真的是O(n² + log(n)),我们称之为O(n²),因为当我们担心log(n)时,谁会关心那个小

因此。看着你的情况。我们做外循环,n次。对于其中的每一个,我们进行内循环n-1次。对于每个内部循环,我们进行第一次打印(任何成本差异都与n无关,因此基本上不变)和测试。测试大约一半时间成功,导致第二次打印的成本经常上升。

所以总费用是:

cost of setting up everything +
n × cost of looping + 
(n - 1) × cost of loop +
(n × (n - 1)) × cost of print +
(n × (n - 1)) × cost of test +
(n × (n - 1)) / 2 × cost of print.

将值分配给上面的常量,我们得到:

k +
n × a +
(n - 1) × b +
(n × (n - 1)) × c +
(n × (n - 1)) × d +
(n × (n - 1)) / 2 × e.

=

k +
n × a +
(n - 1) × b +
(n × (n - 1)) × (c + d + (e / 2))

现在,由于c + d + e / 2本身是常数,因此可以成为:

n × a + (n - 1) × b + (n × (n - 1)) × c + k

或者按照最高订单的顺序重新订购:

(n × (n - 1)) × c + (n - 1) × b + n × a + k

如果n足够高,我们可以给出一个该死的,那么n按比例接近n-1,我们也可以认为它们是相同的(时间复杂度的另一个方面是渐近描述事物,就像n接近∞因此n²和(n×(n-1))之间的差异接近0)。因此:

n² × c + n × b + n × a = n² × c + n × (b + a) + k

同样,b + a本身是常数,所以它相当于:

n² × k + n × c + a

现在我们做了前面提到的吸收较低时间订单的事情,谁关心n × c,没关系?如果n足够高,我们可以完全关心,那么它就是。相比之下,我们可能只考虑作为噪声的总体开销的差异并将其视为:

n² × k + c

或换句话说,如:

O(n²)

所以,是的,你开始就开始使用它,if语句不会影响复杂性。

考虑到这一点,我们可以注意到时间复杂性可能会隐藏我们真正关心的内容。例如,如果我们有一个O(n²)算法,那么这种分析发现n² × k + n × c的时间成本是k达到200μs而c达到15s,那么直到n大于750000它实际上是n比特成本,而不是每n比特。在较低的n,它更接近我们对O(n)的期望,而不是O(n²)。

时间复杂性有用的原因是,如此大的差异是罕见的组合,我们关心时间,因此关于时间复杂性,当n变高时更多(你可以隐藏一些可怕的O(n) !)你的代码中的怪物,你在蓝色的月亮中召唤一次,有三个元素,而且不在乎)。因此,为了实现真实世界的改进,我们理想地希望减少时间复杂度,或者不能降低最高级别常数k(或者换句话说,如果你可以开始做n次n而不是n次,那么不然降低你做n次的事情的成本,而不是你做了n次的其他事情。

换句话说,它有助于我们专注于通常使用的东西。

答案 2 :(得分:0)

当然,如果你正在使用基于比较的算法,那你算什么呢?

所以在你的情况下,你正在看O(n 2 ),因为你的if语句正在执行几乎n 2 次。

对于非比较算法,您可以计算任何主要操作。

答案 3 :(得分:0)

不,if不会影响复杂性。

答案 4 :(得分:0)

时间复杂度相同,你会打印Yayyyy N ^ 2次。

答案 5 :(得分:0)

简短回答:运行时仍为O(N ^ 2)。

长答案:条件检查的成本可以安全地“加”到println操作的权重,就像没有做一个println()一样,你有两个println()。 (关于这个例子,请记住像println这样的I / O操作的成本远远超过简单的整数比较。)

也许您可以说println()调用成本为“1操作”,并且比较为“0.0001操作”,因此总成本将是“(1.0001 * N)^ 2次操作而不是仅仅N ^ 2。你也将println()的数量减少了一半,所以我们可以说你在(1.0001 * N)^ 2/2次操作。这仍然是O(N ^ 2),即使是如果给定N值,则只需打印一半条目就可以将运行时间减半。

通常,比较的成本应该加到由该比较产生的分支内的操作成本中。当if(){}和else {}都存在时,测量运行时可能会更加困难。这里的一个策略是估计运行时,好像每次都发生最昂贵的操作 ;或者,如果单个分支的运行时间不易知道,则估计每次循环迭代都会发生两个操作。如果这些操作都是O(1),则运行时的顺序保持为O(N ^ 2),因为您是线性扩展的。