确定大O表示法

时间:2011-11-30 19:08:59

标签: algorithm big-o

我需要帮助理解/做大O符号。我理解它的目的,我只是不知道如何“确定给定一段代码的复杂性”。

为以下每个

确定Big O表示法

一个。

n=6;
cout<<n<<endl;

n=16;
for (i=0; i<n; i++)
    cout<<i<<endl;

℃。

i=6;
n=23;
while (i<n) {
    cout<<i-6<<endl;
    i++;
}

d。

int a[ ] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
n=10;
for (i=0; i<n; i++)
    a[i]=a[i]*2;
for (i=9; i>=0; i--)
    cout<<a[i]<<endl;

sum=0;
n=6;
k=pow(2,n);
for (i=0;i<k;i++)
    sum=sum+k;

5 个答案:

答案 0 :(得分:7)

大O表示算法的complexity的顺序。

基本的东西:

  • 这种复杂性是根据条目大小来衡量的
  • 您选择单位操作(通常是做作或比较)
  • 您可以计算此操作的调用时间
  • 当使用复杂度时,通常会忽略常数项或常数因子,因此如果操作次数为3 * n ^ 3 + 12,则将其简化为n ^ 3,也标记为O(n ^ 3)

a。)只会运行一次,没有循环,复杂性在这里是微不足道O(1)

b。)在循环中调用n次:O(n)

c。)这里我们选择分析n(因为它通常是算法中的递增变量)。通话次数为n - 6,因此为O(n)

d。)我们假设这里10(n)是数组的大小,9(i)这个大小减1。对于n的每个值,我们必须从0到n然后是n-1到0. n *(n-1)个操作,技术上:O(n * 2)有些人近似为O(n)。两者都称为线性时间,不同的是BigO不关心的线的斜率。

e。)循环从0变为pow(2,n),即1到2 ^ n,总结为O(2^n)

答案 1 :(得分:4)

假设您没有将cout计为Big-O测量的一部分。

<强> A) O(1)您可以在恒定时间内执行整数赋值 的 b)中 O(n)因为循环需要n次操作 的 c)中 O(n-c)= O(n)常数在Big-O中消失 的 D.1) O(2 * n)= O(n)两个线性时间算法最终是线性时间 的 D.2) 如果n随着pow(2,n)= 2 ^ n而增长,则操作次数为O(2 ^ n);然而,如果n是常数,它将随O(k)增长,其中k = 2 ^ 6 = 64,这将是线性的。

答案 2 :(得分:1)

这些例子非常简单。首先,您需要确定代码中的主(简单)操作,并尝试将此操作的调用次数表示为输入函数。

不那么抽象:

一个。)

此代码始终以恒定时间运行。此时间取决于计算机,I / O延迟等 - 但它几乎不依赖于n的值。

湾)

这次循环中的一段代码被执行了好几次。如果n大两倍,你能说一下迭代次数吗?

角)

循环中的一些代码。但这次迭代次数小于n。但是如果n足够大,你是否与b相似?)?

d。)

这段代码很有意思。第一个循环内部的操作更复杂,但同样需要或多或少的恒定时间。那么相对于n执行了多少次?再次与b。)

进行比较

第二个循环只会欺骗你。对于小n,它实际上可能比第一个花费更多时间。但是,O(n)表示法总是考虑高n值。

5。)

最后一段代码实际上非常简单。循环内简单操作的数量等于n^2。将1添加到n,您将获得两倍的操作。

答案 3 :(得分:0)

为了理解完整的数学定义,我推荐维基百科。出于简单的目的,big-oh是算法的上限,给定例程在给定n的长度之前迭代多少次。我们称之为n的上界O(n)或大哦。

在代码中访问c ++中的简单数组的成员是O(1)。无论阵列有多大,它都是一个操作。

for循环中通过数组的线性迭代是O(n)

如果有多个嵌套for循环,则嵌套for循环为O(n ^ 2)或O(n ^ k)

分而治之的递归(堆,二叉树等)取决于操作,是O(lg n)或O(n lg n)。

答案 4 :(得分:0)

<强>一个

n=6;
cout<<n<<endl;

恒定时间,O(1)。这意味着当n从1增加到无穷大时,执行此语句所需的时间量不会增加。每次增加n时,所需的时间不会增加。

b

n=16;
for (i=0; i<n; i++)
    cout<<i<<endl;

线性时间,O(n)。这意味着当n从1增加到无穷大时,执行此语句所需的时间量会线性增加。每次增加n时,前一次所需的额外时间保持不变。

c

i=6;
n=23;
while (i<n) {
    cout<<i-6<<endl;
    i++;
}

线性时间,O(n),与上面的例子2相同。

d

int a[ ] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
n=10;
for (i=0; i<n; i++)
    a[i]=a[i]*2;
for (i=9; i>=0; i--)
    cout<<a[i]<<endl;

线性时间,O(n)。随着n从1增加到无穷大,执行这些语句所需的时间量会线性增加。线性线是示例3的两倍,但是Big O Notation并不关心线的陡峭程度,它只关注时间要求如何增长。随着n的增加,这两个循环需要线性增长的时间。

<强>电子

sum=0;
n=6;
k=pow(2,n);
for (i=0;i<k;i++)
    sum=sum+k;

根据值n:

创建一个执行sum=sum+k次的图表
n     number_of_times_in_loop
1     2^1 = 2
2     2^2 = 4
3     2^3 = 8
4     2^4 = 16
5     2^5 = 32
6     2^6 = 64

当n从1变为无穷大时,请注意我们在循环中的次数是如何呈指数增长的。 2->4->8->16->32->64。如果我插入150的n会怎么样?我们在循环中的次数变得天文数字。

这是指数时间:O(2^n)see here)表示一种算法,其增长将与输入数据集中的每个附加元素加倍。插入一个大型的n你自己的危险,你将等待数小时或数年完成一些输入项目的计算。

我们为什么关心?

作为计算机科学家,我们有兴趣正确理解BigO符号,因为我们希望能够以权威和信念来说出这样的事情:

“Jim用于计算行星之间距离的算法需要指数时间。如果我们想要做20个物体需要花费太多时间,他的代码就是废话,因为我可以在线性时间制作一个。”

更好的是,如果他们不喜欢他们听到的内容,你可以用数学证明它。