五分钟讲解如何计算时间复杂度!408难度

时间复杂度是衡量算法效率的重要指标,主要关注随着问题规模n的增长,算法执行的基本操作次数的数量级。通过分析代码中语句执行的频次,可以简化为如O(n)这样的形式来表示。例如,简单的循环结构可能导致线性时间复杂度O(n),而嵌套循环可能带来平方时间复杂度O(n^2)。加法和乘法法则用于组合不同部分的时间复杂度,帮助我们理解和优化算法性能。
摘要由CSDN通过智能技术生成
时间复杂度的概念

将算法中所有语句被重复执行的次数之和记为T(n),它是问题规模n的函数,时间复杂度主要分析T(n)的数量级。

例如我们观察以下代码:

public static void main(String[] args) {
    int i = 0;
    int n = 10;
    while(i < n){
        System.out.printf("我被执行了%d次!\n", i);
        i++;
    }
}

/*
OUTPUT:
我被执行了0次!
我被执行了1次!
我被执行了2次!
我被执行了3次!
我被执行了4次!
我被执行了5次!
我被执行了6次!
我被执行了7次!
我被执行了8次!
我被执行了9次!

Process finished with exit code 0
*/

上述代码经过简单的分析,不难发现

int i = 0;执行了1

int n = 10;执行了1

System.out.printf("我被执行了%d次!\n", i);执行了10次,因为n为变量(可修改为任何值),记为n次

i++;执行了n次

共计1 + 1 + n + n = 2n+2次,假如每句代码执行时间为1ms,则总执行时间为2n + 2 * 1(ms) = 2n + 2(ms)

时间复杂度的计算
概念

我们现在已经知道时间复杂度是和代码语句的执行次数成正比的关系了,我们经常在各种地方看到O(n),O(n2)等时间复杂度的表达方式,这与我们所说的2n + 2截然不同,这些时间复杂度是如何表示的呢。

其实,时间复杂度仅仅需要分析问题规模函数T(n)的数量级即可,并非需要复杂精细的计算,我们将算法中基本运算(即基础语句)执行的次数的公式记为f(n),则按照上述例子,f(n) = 2n + 2,分析其数量级并记为T(n),T(n)与函数f(n)的对应关系为:
T ( n ) = O ( f ( n ) ) < = = > lim ⁡ n → ∞ T ( n ) f ( n ) = k ( k 为常数 ) T(n)=O(f(n)) <==> \displaystyle\lim_{n\to\infty}\frac {T(n)}{f(n)} = k (k为常数) T(n)=O(f(n))<==>nlimf(n)T(n)=k(k为常数)
这里可能对微积分不了解的朋友看起来会比较晦涩,我们可以这样表示,例如2n + 1,我们可以取公式中最大的n作为其数量级,而 lim ⁡ n → ∞ \displaystyle\lim_{n\to\infty} nlim即为n无限接近无穷大(无穷大可以浅显理解为没有任何一个数比它大),以上公式即可表示为:
lim ⁡ n → ∞ n 2 n + 1 = k ( k 为常数 ) \displaystyle\lim_{n\to\infty}\frac {n}{2n+1} = k (k为常数) nlim2n+1n=k(k为常数)
至于计算过程,我们可以将该公式上下同除n,即可化为: lim ⁡ n → ∞ 1 2 + 1 n \displaystyle\lim_{n\to\infty}\frac {1}{2+\frac{1}{n}} nlim2+n11,而 lim ⁡ n → ∞ 1 n \displaystyle\lim_{n\to\infty}\frac{1}{n} nlimn1可以理解为无限接近于0(因为是1除以一个无穷大的东西,任何常数除以无穷大都近似等0),也就可以相当于0,直接可以得出结果为 1 2 \frac{1}{2} 21,结果为一个常数。

假如不能理解以上计算,也可以直接通过“取大头”的方式计算简单时间复杂度的数量级,如2n2+n+1,即可直接表示为O(n2)。

计算

例如我们观察以下代码:

void cal(int n){
    for(int i = 0; i < n; i++){
        System.out.println("outer");
        System.out.println("outer");
        for(int j = 0; j < n; j++){
            System.out.println("inner");
        }
    }
}

不难发现,其中System.out.println("outer");代码执行了2n次,而System.out.println("inner");执行了System.out.println("看稀罕的");次,System.out.println("看稀罕的");仅执行了一次,我们可以将其总和记为n2+2n+1,通过"取大头"的方法,我们可以直接得出,该代码的时间复杂度为O(n2),其计算过程为:
lim ⁡ n → ∞ n 2 n 2 + 2 n + 1 = lim ⁡ n → ∞ 1 1 + 2 n + 1 n 2 = 1 \displaystyle\lim_{n\to\infty}\frac {n^2}{n^2+2n+1} = \displaystyle\lim_{n\to\infty}\frac {1}{1+\frac{2}{n}+\frac{1}{n^2}}=1 nlimn2+2n+1n2=nlim1+n2+n211=1
灰常的简单。

但是,时间复杂度的计算并非如此简单,我们还可能遇到一些复杂的计算方式,例如:

void cal(int n){
    int i = 0;
    while(i <= n){
        i = i * 2;
    }
}

我们发现,i并非按照加法进行计算,而是按照2, 4, 8, 16...的速度在增加,我们该如何统计它的执行次数呢?

其实,我们可以总结出,它在while中的公式可以写为2x <= n,然后对两边同取对数 log ⁡ 2 \log_2 log2,即可得到 x < = log ⁡ 2 n x<=\log_2n x<=log2n,所以,我们即可得出它的时间复杂度为 log ⁡ 2 n \log_2n log2n

void cal(int n){
    for(int i = 0; i < n; i++){
        System.out.println("outer");
        for(int j = 0; j < n; j = j * 2){
            System.out.println("inner");
        }
    }
}

该代码的时间复杂度是多少呢?可以算一算,很简单*

计算法则

在计算一个程序的时间复杂度时,我们也可以遵循以下公式:

加法法则: T ( n ) = T 1 ( n ) + T 2 ( n ) = O ( f ( n ) ) + O ( g ( n ) ) = O ( m a x ( f ( n ) , g ( n ) ) ) T(n)=T_1(n)+T_2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n))) T(n)=T1(n)+T2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n)))

乘法法则: T ( n ) = T 1 ( n ) ∗ T 2 ( n ) = O ( f ( n ) ) ∗ O ( g ( n ) ) = O ( f ( n ) ∗ g ( n ) ) T(n)=T_1(n)*T_2(n)=O(f(n))*O(g(n))=O(f(n)*g(n)) T(n)=T1(n)T2(n)=O(f(n))O(g(n))=O(f(n)g(n))

计算max时,我们可以遵循以下比例:

O ( 1 ) < O ( l o g 2 n ) < O ( n ) < O ( n l o g 2 n ) < O ( n 2 ) < O ( n 3 ) < O ( 2 n ) < O ( n ! ) < O ( n n ) O(1)<O(log_2n)<O(n)<O(nlog_2n)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n) O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)

复杂度分类

最坏时间复杂度是指在最坏情况下,算法的时间的时间复杂度。

平均时间复杂度是指所有可能得输入实例等概率出现的情况下,算法的期望运行时间。

最好时间复杂度是指在最好情况下,算法的时间的时间复杂度。

*上述答案:O( n l o g 2 n nlog_2n nlog2n)

  • 16
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值