我正试图找到一个很好的解释来快速理解Big O和Theta理论。我总觉得可以通过百万种不同的方式给出解释,我想我正在寻找最终有意义的解释。我知道这是一个n00b问题,但任何帮助都将不胜感激......
答案 0 :(得分:6)
有一点令人困惑的是为什么你可能会想到的是O(2n),对列表中的每个项目执行两个操作的东西,以及你可能认为是O(n)的其他东西实际上都被认为是O( n)的
这样做的原因是,当你开始使用庞大的数据集时,当你考虑O(n ^ 2)或O(n ^ 2)或O(n ^ 2)时,O(2n)和O(n)之间的差异并不是真正的巨大差异。 O(log N)。考虑一下您是否有3种不同的搜索算法来搜索数据集。数据集包含一百万个项目。每个算法将采取的操作数量:
O(2n)= 2,000,000
O(n)= 1,000,000
O(n ^ 2)= 1,000,000,000,000
O(2n)的速度仅为O(n)的2倍,但O(n ^ 2)的速度慢了一百万倍。这是一个令人难以置信的巨大差异! 所以Big O符号实际上是处理算法“缩放”的方式,换句话说,当您考虑越来越大的数据集时,它的表现如何。
O(n ^ 2)算法对于非常小的数据集表现良好,但是对于较大的数据集,其性能会迅速降低。 O(2n)和O(n)将逐渐均匀地降级,这更接近用户在处理更多数据时的预期。
由于这个原因,人们不会谈论O(2n),他们只是谈论O(n),因为两者都代表线性时间(线性的,因为操作数量随着数据的增加而逐渐增加)。
一开始认为某人执行速度慢两倍的算法仍被视为O(n),但大O符号不是相对速度的衡量标准,这可能令人沮丧。 Big O表示法衡量算法如何根据其处理的数据量进行扩展。
答案 1 :(得分:4)
就解释而言,StackOverflow人员似乎从我的 telephone book example 中获益。您可能还需要 Big O For Eight Year Olds 。
答案 2 :(得分:1)
Big O是一种用于比较算法的分析工具。 Big O是函数的上限。将上限视为算法可以运行的最长时间。
Big O经常使用变量n来表示算法中不同数量的元素。例如,如果要对数组的每个元素执行操作,则n将表示数组的大小。您需要执行n次操作。
程序员使用这种表示法有一个共同的基础来说明算法的复杂程度和(如上所述)算法的扩展程度(意味着当n越来越大时它的表现如何)。
用于计算fibonnaci序列的第n个元素的算法对于Big O表示法的目的非常有见地。考虑用于求解fibonnaci序列的第n个元素的递归方法:
fib(n) {
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
return fib(n-1) + fib(n-2);
}
这是Fibonacci的一个简单实现,对于大于100的任何n,运行时间非常慢。我们将此算法分类为O(2 ^ n),它在图上将以指数速度增加。当它处理你的银行账户中的钱时指数很好,但是当它处理算法时很糟糕。
Fibonacci的不同实现可以显着加快算法速度。
fib(n) {
fibArr[n + 1];
fibArr[0] = 0;
fibArr[1] = 1;
for(int i = 2; i <= n; i++) {
fibArr[i] = fibArr[i-1] + fibArr[i-2];
}
return fibArr[n];
}
Fibonnaci的第二个实现具有O(n)的大O运行时间。这就是所谓的线性时间。如果您在图形上相互绘制Fibonnaci的实现,您可以看到与线性实现相比,指数实现的运行时间存在巨大差异。
Size - Linear - Exponential
1 1 2
10 10 1024
100 100 1.2676506e+30
1000 1000 1.071509e+301
将上述每个数字视为需要执行的操作量。如果每个操作需要1毫秒(只是估计),您可以开始猜测算法可能需要多长时间。
Big O分析还有很多其他内容。考虑Big O的这些不同类型的分类。
Constant time - O(1)
Logarithmic - O(logn)
Linear - O(n)
Quadratic - O(n^2)
Exponential - O(2 ^n)
Factorial - O(n!)
选择算法时,了解执行算法所需的近似运行时间和空间非常重要。