满满的一篇,全是复杂度分析核心知识点

今天分享的内容是算法的复杂度分析。

文章内容包括以下几点:

  • 时间复杂度大O记法

  • 时间复杂度分析

  • 常见时间复杂度

  • 最好、最坏、平均情况时间复杂度

  • 均摊时间复杂度

  • 空间复杂度


在淘宝或京东等电商平台进行网络购物时,当输入商品关键字时,就会出现相关的物品推荐;在高德地图上输入起始位置和目标位置,就会有相关路线推荐的推荐。这些APP之所以能根据几个关键字,就给出用户相关的推荐,是因为在其背后有算法在支撑。

提到算法,有两个问题是不可避免的,一个是时间复杂度,可以理解为算法的运行时间,如果算法运行时间太长,那这个算法就没法用;另一个是算法的空间复杂度,可以理解为把算法存储在计算机中需要多大的空间,如果需要空间太大,那这个算法也没法用。因此,需要对一个算法的时间复杂度和空间复杂度进行分析,来确定该算法的可行性。

时间复杂度的分析,一般有两种方法:

  • 事后统计法

  • 事前分析法

事后统计法是用测试程序和数据来运行已编写好的算法,对其执行时间进行比较。这种方法看似可以精确的计算算法的执行时间,但存在一些不足:

  • 一是使用事后统计法的一个前提是,算法已编写好,而编写算法需要大量时间和精力,同时测试程序和数据的准备也是耗时巨大的,这就会出现算法编写好了,测试之后发现用不了的情况,白白浪费大量时间和精力。

  • 二是算法的运行依赖计算机硬件和软件因素。同一个算法在不同的计算机上执行时间是不一样的。在不确定这个算法会用在什么样的计算机上时,少量的测试结果不具备可靠性。

  • 三是算法的执行时间受数据规模的影响。比如对于几个数字的排序,不论是使用选择排序还是插入排序,亦或是快速排序,其执行耗时的差异基本没有。

事前分析法是不依赖具体的测试程序和数据,根据统计方法对算法执行效率进行分析的方法。

01

时间复杂度大O记法

那么,如何在不运行代码的情况下对代码的执行效率进行分析呢?来看一个例子。

public void calculateSum(int n) {
    int sum = 0; // 执行一次
    for(int i = 0; i < n; i++) { // 循环执行n次
        int base = i; // 循环执行n次
        for(int j = 0; j < n; j++) { // 循环执行n*n次
            sum += base + j; // 循环执行n*n次
        }
    }
}

假设每个代码语句每执行一次的耗时是一样的,记为unitTime,所有代码的执行时间,记作T(n)。基于此,上述代码的执行总耗时为T(n)=(1+n+n+n*n+n*n)unitTime=(2n²+2n+1)unitTime。

根据T(n)=(2n²+2n+1)unitTime,可以得出结论:对于一个算法来说,其所有代码的执行总时间T(n)与其每行代码的执行次数n成正比

对于T(n)=(2n²+2n+1)unitTime来说,由于unitTime表示代码中一条语句执行一次的耗时,在这里要分析的是代码执行总时间T(n)和代码执行次数n之间的关系,因此可以不考虑unitTime。此外,2n²+2n+1表示的代码语句的执行总次数,可以将其抽象为f(n)=2n²+2n+1。也就是说,我们用f(n)来抽象表示一个算法的执行总次数。因此可以推导出所有代码的执行总时间T(n)和每行代码的执行次数n之间的关系是:

T(n)=O(f(n))

公式中的O表示代码的执行总时间T(n)和其执行总次数f(n)成正比。这种表示法,称之为大O记法。大O记法T(n)=O(f(n)),表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,表示的是算法的渐近时间复杂度,简称时间复杂度。

02

时间复杂度分析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值