我已经通过谷歌和Stack Overflow搜索,但无处我能够找到一个清楚和直接的解释如何计算时间复杂度。
我已经知道了什么?
比如下面这样简单的代码:
char h = 'y'; // This will be executed 1 time
int abc = 0; // This will be executed 1 time
比如下面这样的循环:
for (int i = 0; i < N; i++) {
Console.Write('Hello, World!!');
}
int i = 0;这将只执行一次。
时间实际上是计算到i=0,而不是声明。
i < N;这将被执行N+1次
i++将执行N次
因此,这个循环所需的操作数为{1+(N+1)+N} = 2N+2。(但这仍然可能是错误的,因为我对自己的理解没有信心。)
好的,这些基本的小计算我知道,但在大多数情况下,我看到的时间复杂度是O(N) O(N²)O(log N) O(N !)等等。
循环的几个例子。
O(n) time complexity of a loop is considered as O(n) if the loop variables is incremented / decremented by a constant amount. For example following functions have O(n) time complexity.
// Here c is a positive integer constant
for (int i = 1; i <= n; i += c) {
// some O(1) expressions
}
for (int i = n; i > 0; i -= c) {
// some O(1) expressions
}
O(nc) time complexity of nested loops is equal to the number of times the innermost statement is executed. For example, the following sample loops have O(n2) time complexity
for (int i = 1; i <=n; i += c) {
for (int j = 1; j <=n; j += c) {
// some O(1) expressions
}
}
for (int i = n; i > 0; i += c) {
for (int j = i+1; j <=n; j += c) {
// some O(1) expressions
}
For example, selection sort and insertion sort have O(n2) time complexity.
O(log n) time complexity of a loop is considered as O(log n) if the loop variables is divided / multiplied by a constant amount.
for (int i = 1; i <=n; i *= c) {
// some O(1) expressions
}
for (int i = n; i > 0; i /= c) {
// some O(1) expressions
}
For example, [binary search][3] has _O(log n)_ time complexity.
O(log log n) time complexity of a loop is considered as O(log log n) if the loop variables is reduced / increased exponentially by a constant amount.
// Here c is a constant greater than 1
for (int i = 2; i <=n; i = pow(i, c)) {
// some O(1) expressions
}
//Here fun is sqrt or cuberoot or any other constant root
for (int i = n; i > 0; i = fun(i)) {
// some O(1) expressions
}
时间复杂度分析的一个例子
int fun(int n)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < n; j += i)
{
// Some O(1) task
}
}
}
分析:
For i = 1, the inner loop is executed n times.
For i = 2, the inner loop is executed approximately n/2 times.
For i = 3, the inner loop is executed approximately n/3 times.
For i = 4, the inner loop is executed approximately n/4 times.
…………………………………………………….
For i = n, the inner loop is executed approximately n/n times.
因此上述算法的总时间复杂度为(n + n/2 + n/3 +…+ n/n),即为n *(1/1 + 1/2 + 1/3 +…+ 1/n)
级数(1/1 + 1/2 + 1/3 +…+ 1/n)的重要之处在于大约是O(log n),所以上面代码的时间复杂度是O(n·log n)。
引用:
1
2
3
这是一篇很好的文章:算法的时间复杂度
下面的答案是从上面复制的(以防优秀的链接崩溃)
计算时间复杂度最常用的度量是大O符号。这样就去掉了所有的常数因子,这样当N趋于无穷时,运行时间就可以相对于N进行估计。一般来说,你可以这样想:
statement;
是恒定的。语句的运行时间不会随着N的变化而改变。
for ( i = 0; i < N; i++ )
statement;
是线性的。循环的运行时间与N成正比,当N加倍时,运行时间也加倍。
for ( i = 0; i < N; i++ ) {
for ( j = 0; j < N; j++ )
statement;
}
是二次。两个循环的运行时间与N的平方成正比,当N翻倍时,运行时间增加N * N。
while ( low <= high ) {
mid = ( low + high ) / 2;
if ( target < list[mid] )
high = mid - 1;
else if ( target > list[mid] )
low = mid + 1;
else break;
}
对数。算法的运行时间与N能被2除的次数成正比。这是因为算法在每次迭代时都将工作区域分成两半。
void quicksort (int list[], int left, int right)
{
int pivot = partition (list, left, right);
quicksort(list, left, pivot - 1);
quicksort(list, pivot + 1, right);
}
为N * log (N)。运行时间由N个对数循环(迭代或递归)组成,因此该算法是线性和对数的结合。
一般来说,对一维中的每一项都做某事是线性的,对二维中的每一项都做某事是二次的,将工作区域一分为二是对数的。还有其他的大O测量方法,如立方、指数和平方根,但它们并不常见。大O符号被描述为O(<类型>),其中<类型>是度量。快速排序算法可以描述为O (N * log(N))。
请注意,所有这些都没有考虑最佳、平均和最坏的情况。每个都有自己的大O符号。还要注意,这是一个非常简单的解释。大O是最常见的,但它也更复杂。还有其他的符号,比如大的,小的o和大的。在算法分析课程之外,你可能不会遇到它们。;)
循环的几个例子。
O(n) time complexity of a loop is considered as O(n) if the loop variables is incremented / decremented by a constant amount. For example following functions have O(n) time complexity.
// Here c is a positive integer constant
for (int i = 1; i <= n; i += c) {
// some O(1) expressions
}
for (int i = n; i > 0; i -= c) {
// some O(1) expressions
}
O(nc) time complexity of nested loops is equal to the number of times the innermost statement is executed. For example, the following sample loops have O(n2) time complexity
for (int i = 1; i <=n; i += c) {
for (int j = 1; j <=n; j += c) {
// some O(1) expressions
}
}
for (int i = n; i > 0; i += c) {
for (int j = i+1; j <=n; j += c) {
// some O(1) expressions
}
For example, selection sort and insertion sort have O(n2) time complexity.
O(log n) time complexity of a loop is considered as O(log n) if the loop variables is divided / multiplied by a constant amount.
for (int i = 1; i <=n; i *= c) {
// some O(1) expressions
}
for (int i = n; i > 0; i /= c) {
// some O(1) expressions
}
For example, [binary search][3] has _O(log n)_ time complexity.
O(log log n) time complexity of a loop is considered as O(log log n) if the loop variables is reduced / increased exponentially by a constant amount.
// Here c is a constant greater than 1
for (int i = 2; i <=n; i = pow(i, c)) {
// some O(1) expressions
}
//Here fun is sqrt or cuberoot or any other constant root
for (int i = n; i > 0; i = fun(i)) {
// some O(1) expressions
}
时间复杂度分析的一个例子
int fun(int n)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < n; j += i)
{
// Some O(1) task
}
}
}
分析:
For i = 1, the inner loop is executed n times.
For i = 2, the inner loop is executed approximately n/2 times.
For i = 3, the inner loop is executed approximately n/3 times.
For i = 4, the inner loop is executed approximately n/4 times.
…………………………………………………….
For i = n, the inner loop is executed approximately n/n times.
因此上述算法的总时间复杂度为(n + n/2 + n/3 +…+ n/n),即为n *(1/1 + 1/2 + 1/3 +…+ 1/n)
级数(1/1 + 1/2 + 1/3 +…+ 1/n)的重要之处在于大约是O(log n),所以上面代码的时间复杂度是O(n·log n)。
引用:
1
2
3