美文网首页
一、复杂度

一、复杂度

作者: 咸鱼Jay | 来源:发表于2022-01-08 07:10 被阅读0次

什么是算法

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



使用不同算法,解决同一个问题,效率可能相差非常大

比如:求第 n 个斐波那契数(fibonacci number)

public static int fib1(int n) {
    if (n <= 1) return n;
    return fib1(n - 1) + fib1(n - 2);
}

public static int fib2(int n) {
    if (n <= 1) return n;
    int first = 0;
    int second = 1;
    for (int i = 0; i < n - 1; i++) {
        int sum = first + second;
        first = second;
        second = sum;
    }
    return second;
}

如何评判一个算法的好坏?

  • 如果单从执行效率上进行评估,可能会想到这么一种方案

    • 比较不同算法对同一组输入的执行处理时间
    • 这种方案也叫做:事后统计法
  • 上述方案有比较明显的缺点

    1. 执行时间严重依赖硬件以及运行时各种不确定的环境因素
    2. 必须编写相应的测算代码
    3. 测试数据的选择比较难保证公正性
  • 一般从以下维度来评估算法的优劣

    1. 正确性、可读性、健壮性(对不合理输入的反应能力和处理能力)
    2. 时间复杂度(time complexity):估算程序指令的执行次数(执行时间)
    3. 空间复杂度(space complexity):估算所需占用的存储空间

下面通过估算程序指令的执行次数算时间复杂度:

public static void test1(int n) {
    // 估算程序指令的执行次数(执行时间)
    // 下面if-else都算1次
    if (n > 10) { 
        System.out.println("n > 10");
    } else if (n > 5) {
        System.out.println("n > 5");
    } else {
        System.out.println("n <= 5"); 
    }
    
    //int i = 0执行1次,i < 4、 i++和println都是执行4次
    // 1 + 4 + 4 + 4 ==> 总共14次
    for (int i = 0; i < 4; i++) {// 1 + 4 + 4 
        System.out.println("test");// 4
    }
}

public static void test2(int n) {
    // 1 + 3n(int i = 0执行1次,i < n、i++和都是执行n次)
    for (int i = 0; i < n; i++) {// 1 + n + n
        System.out.println("test");// n
    }
}

public static void test3(int n) {
    // 1 + 2n + n * (1 + 3n) ==>1 + 2n + n + 3n^2 ==> 3n^2 + 3n + 1

    for (int i = 0; i < n; i++) {//1 + 2n
        for (int j = 0; j < n; j++) {//n * (1 + 3n)
            System.out.println("test");//n
        }
    }
}

public static void test4(int n) {
    // 1 + 2n + n * (1 + 45) ==> 1 + 2n + 46n ==> 48n + 1

    for (int i = 0; i < n; i++) {//1 + 2n
        for (int j = 0; j < 15; j++) {// n * (1 + 45)
            System.out.println("test");//15
        }
    }
}

public static void test5(int n) {
    //假设n=16; 16 = 2^4 、 8 = 2^3 、 4 = 2^2 、 2 = 2^1 、 1 = 2^0
    // 其实就是求指数值
    // 4 = log2(16) 、 3 = log2(8) 、 2 = log2(4) 、 1 = log2(2)
    
    // 执行次数 = log2(n)
    while ((n = n / 2) > 0) {
        System.out.println("test");
    }
}

public static void test6(int n) {
    // log5(n)
    while ((n = n / 5) > 0) {
        System.out.println("test");
    }
}

public static void test7(int n) {
    // 1 + 2*log2(n) + log2(n) * (1 + 3n) ==> 1 + 3*log2(n) + 2 * nlog2(n)
    for (int i = 1; i < n; i = i * 2) {// 1 + 2*log2(n)
        for (int j = 0; j < n; j++) {//  log2(n) * (1 + 3n)
            System.out.println("test");// n
        }
    }
}

大O表示法(Big O)

  • 一般用大O表示法来描述复杂度,它表示的是数据规模n 对应的复杂度
  • 忽略常数、系数、低阶

9 >> O(1)
2n + 3 >> O(n)
n{^2} + 2n +6 >> O(n{^2})
4n{^3} + 3n{^2} + 22n + 100 >> O(n{^3})
写法上,n{^3}等价于n{^3}

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

对数阶的细节

  • 对数阶一般省略底数
    log{_2}n = log{_2}9 * log{_9n}
  • 所以log{_2}nlog{_9n}统称为logn

最终使用大O表示法表示时间复杂度:

public static void test1(int n) {
    // 估算程序指令的执行次数(执行时间)
    // 下面if-else都算1次
    if (n > 10) { 
        System.out.println("n > 10");
    } else if (n > 5) {
        System.out.println("n > 5");
    } else {
        System.out.println("n <= 5"); 
    }
    
    //int i = 0执行1次,i < 4、 i++和println都是执行4次
    // 1 + 4 + 4 + 4 ==> 总共14次
    for (int i = 0; i < 4; i++) {// 1 + 4 + 4 
        System.out.println("test");// 4
    }
    // 时间复杂度:O(1)
}

public static void test2(int n) {
    // 1 + 3n(int i = 0执行1次,i < n、i++和都是执行n次)
    for (int i = 0; i < n; i++) {// 1 + n + n
        System.out.println("test");// n
    }
    // 时间复杂度:O(n)
}

public static void test3(int n) {
    // 1 + 2n + n * (1 + 3n) ==>1 + 2n + n + 3n^2 ==> 3n^2 + 3n + 1
    for (int i = 0; i < n; i++) {//1 + 2n
        for (int j = 0; j < n; j++) {//n * (1 + 3n)
            System.out.println("test");//n
        }
    }
    // 时间复杂度:O(n^2)
}

public static void test4(int n) {
    // 1 + 2n + n * (1 + 45) ==> 1 + 2n + 46n ==> 48n + 1
    for (int i = 0; i < n; i++) {//1 + 2n
        for (int j = 0; j < 15; j++) {// n * (1 + 45)
            System.out.println("test");//15
        }
    }
    // 时间复杂度:O(n)
}

public static void test5(int n) {
    //假设n=16; 16 = 2^4 、 8 = 2^3 、 4 = 2^2 、 2 = 2^1 、 1 = 2^0
    // 其实就是求指数值
    // 4 = log2(16) 、 3 = log2(8) 、 2 = log2(4) 、 1 = log2(2)
    
    // 执行次数 = log2(n)
    while ((n = n / 2) > 0) {
        System.out.println("test");
    }
    // 时间复杂度:O(logn)
}

public static void test6(int n) {
    // log5(n)
    while ((n = n / 5) > 0) {
        System.out.println("test");
    }
    // 时间复杂度:O(logn)
}

public static void test7(int n) {
    // 1 + 2*log2(n) + log2(n) * (1 + 3n) ==> 1 + 3*log2(n) + 2 * nlog2(n)
    for (int i = 1; i < n; i = i * 2) {// 1 + 2*log2(n)
        for (int j = 0; j < n; j++) {//  log2(n) * (1 + 3n)
            System.out.println("test");// n
        }
    }
    // 时间复杂度:O(nlogn)
}

常见的复杂度

函数图像绘制工具

可以借助函数生成工具对比复杂度的大小
函数图像绘制工具

数据规模较小时

数据规模较大时

fib函数的时间复杂度分析


他们的差别有多大

  • 如果有一台1GHz的普通计算机,运算速度10^{9}次每秒( n 为 64 )
  • O(n) 大约耗时 6.4 ∗ 10^{-8}
  • O(2^n) 大约耗时 584.94 年
  • 有时候算法之间的差距,往往比硬件方面的差距还要大

算法的优化方向

  • 用尽量少的存储空间
  • 用尽量少的执行步骤(执行时间)
  • 根据情况,可以
    • 空间换时间
    • 时间换空间

多个数据规模的情况


test方法有两个数据规模(n和k),也就意味着方法体里面的时间复杂度是有n和k决定的,因此这个test方法的时间复杂度是:O(n + k)次数

代码链接

相关文章

  • 算法基础知识

    算法的复杂度 算法的复杂度: 算法的时间复杂度和空间复杂度合称为算法的复杂度,一般不特别说明,讨论的时间复杂度均是...

  • day02 四种时间复杂度分析方法

    一、时间复杂度有哪几种? 最好时间复杂度 最坏时间复杂度 平均时间复杂度(概率) 均摊时间复杂度(特殊的平均时间复...

  • 简单数据结构

    复杂度 一个算法的复杂度,会极大影响程序运行的效率,复杂度又分为时间复杂度和空间复杂度,时间复杂度取决于程序运行时...

  • 冒泡法排序

    1. 空间复杂度、 时间复杂度 空间复杂度: 由于仅需要一个临时变量进行值比较交换,空间复杂度 O(1)时间复杂度...

  • 时间复杂度(下)

    时间复杂度知识点 最好时间复杂度 最坏时间复杂度 平均情况复杂度 均摊时间复杂度

  • 一个好的算法如何测评

    一个算法的好坏可以根据复杂度分析来测评. 复杂度分析包括时间复杂度和空间复杂度. 1.时间复杂度 需要考虑: 1)...

  • 复杂度分析

    为什么需要复杂度分析? 大O复杂度表示法 时间复杂度分析 常见复杂度量级 复杂度量级简单说明 空间复杂度 时间复杂...

  • 复杂度分析笔记

    常见复杂度 :常数复杂度 :对数复杂度 :线性时间复杂度 :线性对数复杂度 :平方阶 :立方 :K次方阶 :指数阶...

  • LeetCode 35. 搜索插入位置

    题目描述 题解 两次遍历 时间复杂度为,空间复杂度为。 一次遍历 时间复杂度为,空间复杂度为。 二分法 时间复杂度...

  • 复杂度分析

    什么是复杂度? 算法的复杂度是粗略衡量一个算法执行效率的方法,分为时间复杂度和空间复杂度。 时间复杂度:估算程序指...

网友评论

      本文标题:一、复杂度

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