时间复杂度

算法复杂度符号介绍

Θ,读音:theta、西塔;既是上界也是下界(tight),等于的意思。

Ο,读音:big-oh、欧米可荣(大写);表示上界(tightness unknown),小于等于的意思。

ο,读音:small-oh、欧米可荣(小写);表示上界(not tight),小于的意思。

Ω,读音:big omega、欧米伽(大写);表示下界(tightness unknown),大于等于的意思。

ω,读音:small omega、欧米伽(小写);表示下界(not tight),大于的意思。

时间复杂度基本概念

我们用T(n) 表示算法执行的次数 。

定义:存在常数 c 和函数 f(n),使得当 n >= c 时 T(n) <= f(n),表示为 T(n) = O(f(n)) 。

当 N >= 2 的时候,f(n) = n^2 总是大于 T(n) = n + 2 的,即T(n) 的增长速度是小于或者等于 f(n)的,也说 f(n) 是 T(n) 的上界,表示为 T(n) = O(f(n))。于是我们说T(n)这个算法的时间复杂度是 O(f(n))。

算法的时间复杂度,用来度量算法的运行时间,记作: T(n) = O(f(n))。它表示随着 输入大小n 的增大,算法执行需要的时间的增长速度可以用 f(n) 来描述。

根据执行次数 T(n)计算时间复杂度

  1. 当 T(n) = c,c 为一个常数时,时间复杂度为 O(1);如果 T(n) 不等于一个常数项时,直接将常数项省略。
如:T(n) = 2,时间复杂度为 O(1)。 T(n) = n + 29,时间复杂度为 O(n)。
  1. 高次项对于函数的增长速度的影响是最大的,因此只保留最高次项。
如:T(n) = n^3 + n^2 + 29,时间复杂度为 O(n^3)。
  1. 函数的阶数对函数的增长速度的影响是最显著的,因此忽略与最高阶相乘的常数。
如:T(n) = 3n^3,此时时间复杂度为 O(n^3)。

推导法则

  1. 对于一个循环,假设循环体的时间复杂度为 O(m),循环次数为 n,则这个循环的时间复杂度为 O(m×n)。
void aFunc(int n) {
    for(int i = 0; i < n; i++) {         // 循环次数为 n
        printf("Hello, World!\n");      // 循环体时间复杂度为 O(1)
    }
}
时间复杂度为 O(1 × n),即 O(n)。
  1. 对于多个循环,假设循环体的时间复杂度为 O(n),各个循环的循环次数分别是a, b, c…,则这个循环的时间复杂度为 O(n×a×b×c…)。分析的时候应该由里向外分析这些循环。
void aFunc(int n) {
    for(int i = 0; i < n; i++) {         // 循环次数为 n
        for(int j = 0; j < n; j++) {       // 循环次数为 n
            printf("Hello, World!\n");      // 循环体时间复杂度为 O(1)
        }
    }
}
时间复杂度为 O(1 × n × n),即 O(n^2)。
  1. 对于顺序执行的语句或者算法,总的时间复杂度等于其中最大的时间复杂度。
void aFunc(int n) {
    // 第一部分时间复杂度为 O(n^2)
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            printf("Hello, World!\n");
        }
    }
    // 第二部分时间复杂度为 O(n)
    for(int j = 0; j < n; j++) {
        printf("Hello, World!\n");
    }
}
时间复杂度为 max(O(n^2), O(n)),即 O(n^2)。
  1. 对于条件判断语句,总的时间复杂度等于其中 时间复杂度最大的路径 的时间复杂度。
void aFunc(int n) {
    if (n >= 0) {
        // 第一条路径时间复杂度为 O(n^2)
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                printf("输入数据大于等于零\n");
            }
        }
    } else {
        // 第二条路径时间复杂度为 O(n)
        for(int j = 0; j < n; j++) {
            printf("输入数据小于零\n");
        }
    }
}
时间复杂度为 max(O(n^2), O(n)),即 O(n^2)。

时间复杂度分析的基本策略是:从内向外分析,从最深层开始分析。如果遇到函数调用,要深入函数进行分析。

练习题

求时间复杂度

void aFunc(int n) {
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            printf("Hello World\n");
        }
    }
}

答案:
执行次数 T(n) = n + (n - 1) + (n - 2)……+ 1 = n(n + 1) / 2 = n^2 / 2 + n / 2。
此时时间复杂度为 O(n^2)。

void aFunc(int n) {
    for (int i = 2; i < n; i++) {
        i *= 2;
        printf("%i\n", i);
    }
}

答案:
假设循环次数为 t,则循环条件满足 2^t < n。
可以得出,执行次数t = log(2)(n),即 T(n) = log(2)(n),可见时间复杂度为 O(log(2)(n)),即 O(log n)。

转自:https://www.jianshu.com/p/f4cca5ce055a
https://blog.csdn.net/liyuming0000/article/details/46929493

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值