在Big O表示法中查找运行时间

时间:2011-02-14 00:28:00

标签: c++ algorithm analysis

1)  for (i = 1; i < n; i++) {                         > n
2)      SmallPos = i;                                 > n-1
3)      Smallest = Array[SmallPos];                   > n-1
4)      for (j = i+1; j <= n; j++)                    >  n*(n+1 -i-1)??
5)          if (Array[j] < Smallest) {                > n*(n+1 -i-1 +1)  ?? 
6)              SmallPos = j;                         > n*(n+1 -i-1 +1)  ?? 
7)              Smallest  = Array[SmallPos]           > n*(n+1 -i-1 +1)  ??     
            }                                         
8)      Array[SmallPos] = Array[i];                   > n-1
   9)                Array[i] = Smallest;             > n-1
                                     }

我知道大O符号是n ^ 2(我的坏不是n ^ 3)

我不确定第4-7行是否有人愿意帮忙? 我不知道如何获得第二个循环的输出,因为j = i + 1,因为我改变了j

同样对于第4行,ans假设为n(n + 1)/ 2 -1我想知道为什么我永远无法得到那个

我并没有真正解决大O的问题我试图将大O的步骤作为常量并且变量在大O符号中被取代。

4 个答案:

答案 0 :(得分:3)

我想说这是O(n ^ 2)(虽然Fred上面指出,O(n ^ 2)是O(n ^ 3)的一个子集,所以说它是O(n并不是错的^ 3))。

请注意,通常没有必要计算每一行的执行次数;因为Big-O表示法会丢弃低阶项,所以仅关注最执行的部分(通常位于最内部循环内部)就足够了。

所以在你的情况下,没有一个循环受Array中的值的影响,所以我们可以安全地忽略所有这些。最里面的循环运行(n-1) + (n-2) + (n-3) + ...次;这是一个arithmetic series,因此在 n ^ 2 中有一个术语。

答案 1 :(得分:2)

这是给你的算法,还是你写的算法?

我认为你的循环索引是错误的。

for (i = 1; i < n; i++) {

应该是

for (i = 0; i < n; i++) {     

for (i = 1; i <= n; i++) {     

取决于数组索引是从0还是1开始(在C和Java中为0)。

假设我们将其更正为:

for (i = 0; i < n; i++) {
    SmallPos = i;
    Smallest = Array[SmallPos];
    for (j = i+1; j < n; j++)
        if (Array[j] < Smallest) {
            SmallPos = j;
            Smallest  = Array[SmallPos];
        }                                         
    Array[SmallPos] = Array[i];
    Array[i] = Smallest;
}

然后我认为复杂性是n 2 -3 / 2n = O(n 2 )。

以下是......

最内层循环中最昂贵的操作(我的讲师称之为“基本操作”)是第5行的关键比较。每循环执行一次。

现在,你创建一个总和:

Sum(i=0 to n-1) of Sum(j=i+1 to n-1) of 1.

现在展开最里面(最右边)的Sum得到:

Sum(i=0 to n-1) of (n-1)-(i+1)+1

然后:

Sum(i=0 to n-1) of n-i-1

然后:

[Sum(i=0 to n-1) of n] - [Sum(i=0 to n-1) of i] - [Sum (i=0 to n-1) of 1]

然后:

n[Sum(i=0 to n-1) of 1] - [(n-1)(n)/2] - [(n-1)-0+1]

然后:

n[(n-1)-0+1] - [(n^2-n)/2] - [n]

然后:

n^2 - [(n^2/2) - n/2] - n

等于:

1/2n^2 - 1/2n

在:

O(n^2)

如果你问为什么它不是O(n 3 )......

考虑最坏的情况。 <{1}}如果if (Array[j] < Smallest)被反向排序,则Array将是最多的。

然后你有一个如下所示的内循环:

    Array[j] < Smallest;
    SmallPos = j;
    Smallest  = Array[SmallPos];

现在我们为每个内部for (j...)循环都有一个常量的三个操作。

而O(3)= O(1)。

实际上,ij确定了我们的工作量。内部if循环中的任何内容都不会改变任何内容。

你可以想到它,因为你应该只计算while和for循环。


至于为什么for (j = i+1; j <= n; j++)是n(n + 1)/ 2。它被称为算术系列。

n-1for (j...)i==0n-2等处通过时,您正在i==1n-3次传递0

所以总和是

n-1 + n-2 + n-3 + ... 3 + 2 + 1

现在,你从外面总结对,重写为:

n-1+1 + n-2+2 + n-3+3 + ...

等于:

n + n + n + ...

并且这些对中有n / 2对,所以你有:

n*(n/2)

答案 2 :(得分:0)

两个for()循环,外循环从1到n,内循环在1..n到n之间运行。这使它成为O(n ^ 2)。

如果你'画出',它将是三角形,而不是矩形,所以O(n ^ 2)虽然是真的,却隐藏了常数因子项更小的事实比如果内循环也从1迭代到n。

答案 3 :(得分:0)

是O(n ^ 2)。

对于外循环的n次迭代中的每次迭代,在内循环中都有n次迭代。