干货!两种方法带你分析时间复杂度!最全常见的时间复杂度实例!

1. 嵌套代码的复杂度 = 嵌套内外代码复杂度的乘积 

示例:双for循环嵌套

for (int i = 0; i < n; i++) {       // O(n)
    for (int j = 0; j < n; j++) {   // O(n)
        // ... 
    }
}

整个循环的时间复杂度是:T(n) = T1(n) * T2(n) = O(n*n) = O(n^{2})。

2.寻找执行次数最多的那部分代码

当我们看代码的运行时间时,不是所有部分都同样重要。其实,我们要找的是执行次数最多的那部分代码。所以,如果你的代码由几部分组成,你就要从代码的各个部分中,选择那个执行次数最多的那部分代码作为整体的复杂度。

示例:

for (int i = 0; i < 100; i++) {  // 跟n无关
    // ... 
}

for (int i = 0; i < n; i++) {  // O(n)
    // ...
}

for (int i = 0; i <= n; ++i) { //O(n^2)
   // ...
     for (int j = 0; j <= n; ++j) {
      // ... 
     }
}

以上代码,第一部分for循环,代码执行了100次,有明确的执行次数,即为常量的执行时间,跟n无关。第二部分for循环,时间复杂度是O(n),第三部分for循环,时间复杂度是O(n^{2})。那么 整段代码的时间复杂度是:T(n)=T1(n)+T2(n)=max(O(f(n)), O(g(n))) =O(max(f(n), g(n)))=O(n^{2})。

3.常见的时间复杂度实例

线性阶和平方阶这里就不过多介绍了。可以看我之前的文章。小白都能看懂的时间复杂度解析

常量阶O(1):代码的执行时间不随 n 的变化而变化。不管代码有多少行,只要跟n无关,那么时间复杂度都是O(1)。

示例:

 int i = 3;
 int j = 5;
 int sum = i + j;

对数阶O(logn):我用下面这段代码解释。

 i=1;
 while (i <= n)  {
   i = i * 2;
 }

从代码中可以看出,变量 i 的值从 1 开始取,每循环一次就乘以 2。当大于 n 时,循环结束。我们把i的值以依次列出来:

根据i的值,可以看出来,这段代码第3行的执行次数是x,当2^{x}=n时,是最后一次循环,也就是这个循环的临界点。通过这个公式:2^{x}=n,我们可以得出x = log_{2}^{n},所以这段代码的复杂度是O(log_{2}^{n})。同理,这类代码的复杂度还可以有O(log_{3}^{n})、O(log_{5}^{n})等,这里有一个重要结论:不管是以3为底,还是5为底,我们可以把所有对数阶的时间复杂度都记为 O(logn)。根据对数的特性,我用以下方式来表示对数复杂度:

公式中的低阶、常量、系数三部分并不影响左右增长趋势。所以,采用对数表达复杂度的时候,我们忽略对数的“底”,统一表示为 O(logn)。

线性对数阶O(nlogn):O(nlogn)其实等于 O(n)乘以O(logn),也就是说上面的代码我们循环n遍时间复杂度就是O(nlogn)。

示例:

i=1;
for(int j = 0;j<=n;j++){
    while (i <= n) {
        i = i * 2;
    }
}
 

指数阶O(2^{n}):经典的例子就是计算斐波那契数列的递归版本:我用下面这段代码解释。

long indexFunc(int n) {
     if (n <= 1) {
        return 1;
     } else {
        return indexFunc(n - 1) + indexFunc(n - 2);
     }
}

这段代码有两个递归调用,我们可以把它的时间复杂度表示为: T(n) = T(n - 1) + T(n - 2) ,这个公式就是著名的斐波那契数列。经过一系列推导,我们可以的得到n >= 1 时,T(n) < (\frac{5}{3})^n,当 n > 4 时,T(n) >= (\frac{3}{2} )^n。所以,最后这段代码的时间复杂度可以简化为O(2^{n})。

阶乘阶O(n!):大多数实际情境中,阶乘阶的时间复杂度是不可接受的,因为它比指数时间复杂度还要坏。具体地说,如果一个算法的时间复杂度是 O(n!),它意味着随着输入大小 n 的增长,算法的运行时间会以非常快的速度增长。一个经典的有这种时间复杂度的问题是旅行商问题,有兴趣的大家可以去搜索看一看。

感谢大家的观看!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值