• 算法的时间及空间复杂度


    🍓 简介:java系列技术分享(👉持续更新中…🔥)
    🍓 初衷:一起学习、一起进步、坚持不懈
    🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏
    🍓 希望这篇文章对你有所帮助,欢迎点赞 👍 收藏 ⭐留言 📝

    🍓 更多文章请点击
    在这里插入图片描述在这里插入图片描述

    一、 什么是算法?

    • 能够对一定规范的输入,在有限时间内获得所要求的输出
    • 不同的算法可能用不同的时间、空间或效率来完成同样的任务。
    • 一个算法的优劣可以用空间复杂度时间复杂度来衡量。

    二、 算法初体验

    一个优秀的算法追求以下两个目标:

    1. 花最少的时间完成需求
    2. 占用最少的内存空间完成需求

    案例1 计算1到100的和。

    第一种解法

    public static void main(String[] args) { 
        int sum = 0;
        int n=100;
        for (int i = 1; i <= n; i++) {
            sum += i;
        }  
        System.out.println("sum=" + sum);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    第二种解法

     public static void main(String[] args) {
            int sum = 0;
            int n=100;
            sum = (n+1)*n/2;
            System.out.println("sum="+sum);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    很明显,第二种算法完成需求,花费的时间更少一些。

    案例2 计算10的阶乘

    第一种解法

    public class Test {
        public static void main(String[] args) {
            //测试,计算10的阶乘
            long result = fun1(10);
            System.out.println(result);
        }
        //计算n的阶乘
        public static long fun1(long n){
            if (n==1){
                return 1;
            }
            return n*fun1(n-1);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    第二种解法

    public class Test {
        public static void main(String[] args) {
            //测试,计算10的阶乘
            long result = fun2(10);
            System.out.println(result);
        }
        //计算n的阶乘
        public static long fun2(long n){
            int result=1;
            for (long i = 1; i <= n; i++) {
                result*=i;
            }
            return result;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    第一种解法,使用递归完成需求,fun1方法会执行10次,并且第一次执行未完毕,调用第二次执行…最终,最多的时候,需要在栈内存同时开辟10块内存分别执行10个fun1方法。

    第二种解法,使用for循环完成需求,fun2方法只会执行一次,最终,只需要在栈内存开辟一块内存执行fun2方法即可。

    很明显,第二种算法完成需求,占用的内存空间更小。

    三、 算法的复杂度分析

    3.1 时间复杂度分析

    事后分析估算方法:
    这种方法有很大的缺陷:必须依据算法实现编制好的测试程序,通常要花费大量时间和精力,测试完了如果发现测试的是非常糟糕的算法,那么之前所做的事情就全部白费了,并且不同的测试环境(硬件环境)的差别导致测试的结果差异也很大。
    事前分析估算方法:
    在计算机程序编写前,依据统计方法对算法进行估算,这包括对算法的时间复杂度进行分析,以了解算法随问题规模n的变化情况并确定其数量级。这种分析可以帮助程序员在编写代码之前预测代码的运行时间,从而更好地优化代码和数据结构,提高代码运行效率。

    3.1.1 案例 计算1到100的和,逐行解析

    第一种
    如果输入量n为1亿,则需要计算1亿次;

    public static void main(String[] args) {
        int sum = 0;//执行1次
        int n=100;//执行1次
        for (int i = 1; i <= n; i++) {//执行了n+1次
            sum += i;//执行了n次
        }
        System.out.println("sum=" + sum);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    第二种
    如果输入量n为1亿,则需要计算1次;

    public static void main(String[] args) {
            int sum = 0;//执行1次
            int n=100;//执行1次
            sum = (n+1)*n/2;//执行1次
            System.out.println("sum="+sum);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    经过一系列的研究,通过函数渐近增长分析,这里将结论总结如下:

    比较算法随着输入规模的增长量时,可以有以下规则:

    1.算法函数中的常数可以忽略;

    2.算法函数中最高次幂的常数因子可以忽略;

    3.算法函数中最高次幂越小,算法效率越高。

    3.1.2 算法时间复杂度

    3.1.2.1 大O记法

    ​在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随着n的变化情况并确定T(n)的量级。算法的时间复杂度,就是算法的时间量度,记作:T(n)=O(f(n))。它表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称时间复杂度,其中f(n)是问题规模n的某个函数。
    用大写O()来体现算法时间复杂度的记法,我们称之为大O记法。一般情况下,随着输入规模n的增大,T(n)增长最慢的算法为最优算法。

    下面我们使用大O表示法来表示一些求和算法的时间复杂度:
    如果忽略判断条件的执行次数和输出语句的执行次数,那么当输入规模为n时,以上算法执行的次数分别为:
    ​算法一:3次
    算法二:n+3次
    ​算法三:n^2+2次

    如果用大O记法表示上述每个算法的时间复杂度,应该如何表示呢?基于我们对函数渐近增长的分析,推导大O阶的表示法有以下几个规则可以使用:

    1. 用常数1取代运行时间中的所有加法常数;

    2. 在修改后的运行次数中,只保留高阶项;

    3. 如果最高阶项存在,且常数因子不为1,则去除与这个项相乘的常数;

    所以,上述算法的大O记法分别为:

    ​ 算法一:O(1)
    ​ 算法二:O(n)
    ​ 算法三:O(n^2)

    3.1.2.2. 最坏情况

    有一个存储了n个随机数字的数组,请从中查找出指定的数字。

    public int search(int num){
        int[] arr={11,10,8,9,7,22,23,0};
        for (int i = 0; i < arr.length; i++) {
            if (num==arr[i]){
                return i;
            }
        }
        return -1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    最好情况:

    ​ 查找的第一个数字就是期望的数字,那么算法的时间复杂度为O(1)

    最坏情况:

    ​ 查找的最后一个数字,才是期望的数字,那么算法的时间复杂度为O(n)

    平均情况:

    ​ 任何数字查找的平均成本是O(n/2)

    最坏情况是一种保证,在应用中,这是一种最基本的保障,即使在最坏情况下,也能够正常提供服务,所以,除非特别指定,我们提到的运行时间都指的是最坏情况下的运行时间。

    3.2 空间复杂度分析

    计算机的软硬件都经历了一个比较漫长的演变史,作为为运算提供环境的内存,更是如此,从早些时候的512k,经历了1M,2M,4M…等,发展到现在的8G,甚至16G和32G,所以早期,算法在运行过程中对内存的占用情况也是一个经常需要考虑的问题。我么可以用算法的空间复杂度来描述算法对内存的占用。

    1.基本数据类型内存占用情况:

    数据类型内存占用字节数
    byte1
    short2
    int4
    long8
    float4
    double8
    boolean1
    char2
    • 由于现在的计算机设备内存一般都比较大,基本上个人计算机都是4G起步,大的可以达到32G,所以内存占用一般情况下并不是我们算法的瓶颈
    • 注意空间复杂度是衡量算法在运行过程中使用的内存大小,而不是指程序代码本身的大小。因此,在分析空间复杂度时,需要考虑算法在执行过程中所创建的临时变量、数据结构以及其他相关的内存使用情况。
    • 普通情况下直接说复杂度,默认为算法的时间复杂度。
    • 但是,如果你做的程序是嵌入式开发,尤其是一些传感器设备上的内置程序,由于这些设备的内存很小,一般为几kb,这个时候对算法的空间复杂度就有要求了,但是一般做java开发的,基本上都是服务器开发,一般不存在这样的问题。

    后续持续更新............................

    在这里插入图片描述在这里插入图片描述

  • 相关阅读:
    数据库系统原理与应用教程(006)—— 编译安装 MySQL5.7(Linux 环境)
    Mybatis和Spring集成
    2022年高教社杯国赛C题思路 : 古代玻璃制品的成分分析与鉴别
    从技术体系到商业洞察,中小研发团队架构实践之收尾篇
    51单片机的简易篮球计分器倒计时仿真设计( proteus仿真+程序+原理图+报告+讲解视频)
    Spring:IOC/DI注解开发(7)
    dubbo&&zookeeper面试题
    IDEA文件UTF-8格式控制台输出中文乱码
    神经网络分析教学目标,神经网络分析教学反思
    远程桌面登录Windows云服务器报错0x112f
  • 原文地址:https://blog.csdn.net/qq_41805567/article/details/132759428