数据结构时间和空间复杂度简单分析

本文深入解析算法的时间和空间复杂度,包括大O记法、常见复杂度实例及分析方法,帮助理解算法效率与数据规模间的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

三、时间复杂度分析
   上个章节中对大O时间复杂度分析做了阐述,这个章节看一下如何在具体的算法中准确的分析出时间复杂度。

1.只关注执行次数最多的一段代码
    如前文说到,低阶、常量、系数都会随数据规模的增大而变的无关紧要因此被忽略。那么在实际分析时间复杂度的时候,我们便可忽略这部分内容而直接去看代码中执行次数最多的一段代码。如上述示例一中,执行最多的就是for循环那部分执行了n次,因此它的时间复杂度就是O(n),示例二中执行最多的是嵌套内部的for循环,它执行了n²次,因此复杂度为O(n²)。

2.加法法则:总复杂度等于量级最大的那段代码的复杂度
   这个原则与上述原则实际相同,也就是在推倒开始到最后结果的过程,还是示例一种,第二行执行了一次,时间复杂度是O(1)常数级别,后边的代码时间复杂度是O(n),加一起之后取最大的就是O(n)。示例二也如此,可推出是O(n²)。

3.乘法法则:嵌套的代码段时间复杂度等于嵌套内外代码复杂度的乘积
   在示例二中,嵌套了一个代码段,外层代码时间复杂度O(n),内层代码时间复杂度O(n),但是外层每执行1次,内层就要执行n次,因此最后的时间复杂度等于二者的乘积O(n²)。

四、几种常见时间复杂度实例分析
    虽然算法有很多种,但是常见的时间复杂度量级并不多,按照量级可以分为两种,一种是多项式量级:

常量阶O(1)、对数阶O(logn)、线性阶O(n)、线性对数阶(Onlogn)、平方阶O(n²)、立方阶O(n³)....k次方阶O(n^k)

另一种是非多项式量级:

指数阶O(2^n)、阶乘阶O(n!)

对于非多项式量级,随着执行次数增长,执行时间会急剧增加,因此暂不讨论这种情况。主要看多项式量级的几种复杂度。

1.O(1)
    O(1)并不是表示只执行了一行代码,而只是常量级用来表示时间复杂度的方式。即便如下三行代码的代码段,他的时间复杂度也是O(1)而不是O(3),O(1)时间复杂度常用于代码的执行时间不会随执行次数n线性增长的代码段。通俗来说就是代码中不存在复杂的逻辑结构,如循环、递归等。

int a = 9;
int b = 1;
int sum = a+b;
2.O(logn)、O(nlogn)
    对数阶复杂度比较常见,也相对复杂,看如下代码:

    public void sum(int n){
        int i=1;
        while(i<n){
            i = i*2;
        }
    }
    根据前边的分析,我们只需要看while循环的复杂度就可以了。从代码中可以看出,变量i从1开始,每一次循环就乘以2,直到大于或等于n的时候结束,因此变量i的值实际上就是一个形如2^0 2^1 2^2......2^x = n的等比数列,只要求出x的值就知道这段代码的执行次数了。2^x = n 数学计算x = log2n,所以如上代码的时间复杂度为O(log2n),那么如上代码如果变成i = i*3呢?时间复杂度就变成了O(log3n),在数学计算中,log3n等于log3^2 * log2n,因为log3^2是常数,所以可以忽略,因此log3n=log2n,为了方便起见,不管底数是什么,统一记做成logn,也就是上述两种情况的时间复杂度都为O(logn),对于O(nlogn)就比较好理解了,而根据乘法法则,在O(logn)外层嵌套了一个O(n)复杂度的循环,如for,那么这段代码的时间复杂度就是O(nlogn)

3.O(m+n)、O(m*n)
    前边讲过了加法法则和乘法法则,有如下代码段:

    public void sum(int m,int n){
        int sum = 0;
        for(int i =0;i<m;i++){
            sum++;
        }
        for(int j=0;j<n;j++){
            sum++;
        }
    }
    对于第一个循环,时间复杂度为O(m),第二个for循环时间复杂度则为O(n),根据加法法则,二者相加之后时间复杂度为O(m+n)

    再看另一个代码段:

    public void sum(int m,int n){
        int sum = 0;
        for(int i =0;i<m;i++){
            for(int j=0;j<n;j++){
                sum++;
            }
        }
    }
    对于第一个for循环,时间复杂度为O(m),第二个for循环时间复杂度为O(n),因为是嵌套关系,所以根据乘法法则,这段代码的时间复杂度为O(m*n)

    对于第一种情况,因为不确定m和n的大小关系,因此无法像n+1一样把常数省略。

五、空间复杂度分析
    如上的学习都是针对大O时间复杂度分析,时间复杂度表示算法的执行时间与数据规模的关系,类比一下空间复杂度就是算法的空间占用与数据规模的关系。有如下代码段:

    public void print(int n){
        int i =0;
        int[] a = new int[n];
        for(;i<n;i++){
            a[i] = i;
        }
        for(i=n-1;i>=0;i--){
            System.out.println(a[i]);
        }
    }
    空间复杂度分析的是存储使用情况,因此无需分析执行时间,但是分析方式相同。第二行代码中,我们申请了一个空间存储变量,他是常量阶的,因此跟数据规模没有关系。再看第三行代码,申请了长度为n的数组空间,因此它的空间复杂度为O(n),而后边的代码都没有用到空间申请,因此这个代码段的空间复杂度就是O(n)

    常用的空间复杂度就是O(1)、O(n)、O(n²),对数阶复杂度一般情况下是用不到的。
--------------------- 
作者:Crayoncxy 
来源:优快云 
原文:https://blog.youkuaiyun.com/chenxyt/article/details/82881845 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值