01-复杂度

作者: 紫荆秋雪_文 | 来源:发表于2020-11-12 22:02 被阅读0次

    铭记:

    \color{#DC143C}{算法 + 数据结构 = 程序}

    一、什么是算法

    算法是用于解决特定问题的一系列的执行步骤

    • 使用不同的算法,解决同一个问题,效率可能相差非常大
    • 斐波那契数列

    0、1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)

    算法一:使用递归求和

        /**
         * 斐波那契数列(算法一)
         * @param index 下标位置
         * @return index 位置的数值
         * 下标:0、1、2、3、4、5、6、7、  8、 9、.... n
         * 数值:0、1、1、2、3、5、8、13、21、34
         */
        private static Integer fibonacci1(Integer index) {
            if (index < 2) {
                return index;
            }
            // 使用递归求和
            return fibonacci1(index - 1) + fibonacci1(index - 2);
        }
    

    算法二:使用 for 循环求和(性能更高)

    0、1、1、2、3、5、8、13、21、34、……n
    n = 2 :F(2) = F(1) + F(0),循环1次
    n = 3 : F(3) = F(2) + F(1),循环2次
    n = 4 :F(4) = F(3) + F(2),循环3次
    ...
    n :F(n) = F(n - 1) + F(n - 2),循环n-1次

        /**
         * 斐波那契数列(算法二)
         * @param index 下标位置
         * @return index 位置的数值
         * 下标:0、1、2、3、4、5、6、7、  8、 9、.... n
         * 数值:0、1、1、2、3、5、8、13、21、34
         */
        private static Integer fibonacci2(Integer index) {
            Integer first = 0;
            Integer second = 1;
            if (index < 2) {
                return index;
            }
            /**
             * 求index位置上的数值,其实就是求 index-1 和 index-2 位置上的数值之和
             *
             * 所以可以通过遍历来实现
             */
            Integer sum = 0;
            for (int i = 1; i < index; i++) {
                sum = first + second;
                first = second;
                second = sum;
            }
            return sum;
        }
    

    算法二代码优化

        /**
         * 斐波那契数列(算法二)
         * @param index 下标位置
         * @return index 位置的数值
         * 下标:0、1、2、3、4、5、6、7、  8、 9、.... n
         * 数值:0、1、1、2、3、5、8、13、21、34
         */
        private static Integer fibonacci2(Integer index) {
            Integer first = 0;
            Integer second = 1;
            if (index < 2) {
                return index;
            }
            /**
             * 求index位置上的数值,其实就是求 index-1 和 index-2 位置上的数值之和
             *
             * 所以可以通过遍历来实现
             */
            for (int i = 1; i < index; i++) {
                second += first;
                first = second - first;
            }
            return second;
        }
    

    测试算法

        public static void main(String[] args) {
            Integer n = 10;
            long startTime = System.currentTimeMillis();
            Integer integer = fibonacci1(n);
    //        Integer integer = fibonacci2(n);
            long endTime = System.currentTimeMillis();
            long tiem = endTime - startTime;
            System.out.println("下标为 " + n + "的数据为:" + integer + " 用时:" + tiem);
        }
    
    • 测试结果如下,通过测试结果可以算法二的性能更高
    当n = 10时
    算法一:下标为 10的数据为:55 用时:0ms
    算法二:下标为 10的数据为:55 用时:0ms
    当n = 20时
    算法一:下标为 20的数据为:6765 用时:2ms
    算法二:下标为 20的数据为:6765 用时:0ms
    当n = 30时
    算法一:下标为 30的数据为:832040 用时:42ms
    算法二:下标为 30的数据为:832040 用时:0ms
    当n = 40时
    算法一:下标为 40的数据为:102334155 用时:1751ms
    算法二:下标为 40的数据为:102334155 用时:0ms
    当n = 48时
    算法一:下标为 48的数据为:512559680 用时:62664ms
    算法二:下标为 48的数据为:512559680 用时:0ms
    

    二、算法的好坏

    一般从以下纬度来评估算法的优劣

    • 正确性、可读性、健壮性(对不合理输入的反应能力和处理能力)
    • \color{#DC143C}{时间复杂度}:估算程序指令的执行次数(执行时间)
    • \color{#DC143C}{空间复杂度}:估算所需占用的存储空间

    三、大O表示法

    一般用大O表示法来描述复杂度,它表示的是数据规模 n 对应的复杂度

    忽略常数、系数、低阶

    • 9 \color{#DC143C}{>>} O(1)
    • 2n + 1 \color{#DC143C}{>>} O(n)
    • n² + 2n +2 \color{#DC143C}{>>} O(n²)
    • 3n³ + 2n² + 1n +100 \color{#DC143C}{>>} O(n³)

    注意:大O表示法仅仅是一种粗略的分析模型,是一种估算,能帮助我们短时间内了解一个算法的执行效率 时间复杂度大O表示法.png

    • 复杂度表
    • 复杂度-小规模数据 复杂度-小规模数据.png
    • 复杂度-大规模数据 复杂度-大规模数据.png

    斐波那契数列的时间复杂度

    0、1、2、3、4、5、6、7、8、。。。n
    0、1、1、2、3、5、8、13、21、34...

    算法一的时间复杂度 算法一-时间复杂度1.png

    算法一-时间复杂度2.png
    • 当n=5时,约等于 2(n-1)(20+21+22+23-2+24-14 = 20+21+22+23+2^4-16)
    • 当n=6时,约等于 2(n-1)(20+21+22+23+24-8+2^5-30 = 20+21+22+23+24+25-38)
    • 所以算法一的时间复杂度为O(2^n)

    算法二的时间复杂度

    n = 2 :F(2) = F(1) + F(0),循环1次
    n = 3 : F(3) = F(2) + F(1),循环2次

    n = 4 :F(4) = F(3) + F(2),循环3次
    ...
    n :F(n) = F(n - 1) + F(n - 2),循环n-1次

    • 所以算法二的时间复杂度为O(n)

    相关文章

      网友评论

        本文标题:01-复杂度

        本文链接:https://www.haomeiwen.com/subject/hhhjbktx.html