复杂度

作者: code希必地 | 来源:发表于2020-12-23 21:54 被阅读0次

1、什么是算法

算法就是解决特定问题的一系列执行步骤。
下面用两种不同的算法来实现获取第n个斐波那契数,在讲这个例子之前,先来说下什么是斐波那契。
斐波那契数又称为"[兔子数列]",指的是这样一个数列: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。
下面我们就使用递归和非递归的方式来实现。

1.1、递归方式

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

1.2、迭代方式

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

2、如何判断一个算法的好坏

我们一般从如下方面判断算法的好坏:

  • 正确性、可读性、健壮性
  • 时间复杂度:估算程序指令执行的时间。
  • 空间复杂度:估算所占用内存空间。
    下面就来看下如何描述复杂度。

3、大O表示法

  • 一般用大O表示法来描述复杂度,它表示的是数据规模n对应的复杂度。
    下面举例看下如何使用大O表示法来描述时间复杂度。
public static void test1(int n) {
    // 下面判断只会执行一次(判断条件忽略不计) 计为1
    if (n > 10) {
        System.out.println("n > 10");
    } else if (n > 5) { // 2
        System.out.println("n > 5");
    } else {
        System.out.println("n <= 5");
    }

    /**
     * i = 0只会初始化一次 计为1 i < 4会执行4次 计为4 i++ 会执行4次 计为4 test输出4次 计为4 则循环共执行1+4+4+4
     */
    for (int i = 0; i < 4; i++) {
        System.out.println("test");
    }
    // 上面代码共执行1+1+4+4+4=14次
    // 大O表示法会忽略常数所以复杂度为O(1)
}

public static void test2(int n) {
    // 分析同test() 循环会执行1 + 3n
    for (int i = 0; i < n; i++) {
        System.out.println("test");
    }
    // 忽略常数,复杂度为O(n)
}

public static void test3(int n) {
    /**
     * 内部循环会执行1+3n次 则执行的次数为1+2n+n*(1+3n)=1+3n+3n^2 忽略常数、系数和低阶,复杂度为O(n^2)
     */
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            System.out.println("test");
        }
    }
}

public static void test4(int n) {
    /**
     * 分析同test3(),执行次数为1+2n+n*(1+15+15+15)=1+48n 复杂度为O(n)
     */
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 15; j++) {
            System.out.println("test");
        }
    }
}

public static void test5(int n) {
    /**
     * 执行次数表示为n可以被2除多少次, 即log2(n)次 复杂度为(logn)
     */
    while ((n = n / 2) > 0) {
        System.out.println("test");
    }
}

public static void test6(int n) {
    //同上,复杂度为O(logn)
    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)
    // O(nlogn)
    for (int i = 1; i < n; i = i * 2) {
        // 1 + 3n
        for (int j = 0; j < n; j++) {
            System.out.println("test");
        }
    }
}
  • 使用大O表示法,一般忽略常数、系数、低阶
执行次数 复杂度
9 O(1)
2n+3 O(n)
n²+2n+8 O(n²)
4n³+3n²+8n+22 O(n³)
4log₂n+25 O(logn)
3n+2nlog₂n+15 O(nlogn)
  • 注意:大O表示法仅仅是粗略的估算,能帮助我们短时间内了解一个算法的执行效率。
  • 对数阶一般省略底数
    log₂n=log₂9*log₉n
  • 所以log₂n、log₉n统称为logn
  • 复杂度的大小排序如下:
    O(1)< O(logn) < O(n) < O(nlogn) < O(n²) < O(n³) < O(2^n) < O(n!) < O(n^n)
    了解了如何用大O表示法表示复杂度,以及复杂度的大小排序,下面看下我们刚开始使用迭代和递归两种方式实现的斐波那契的复杂度。

4、斐波那契两种实现方法的复杂度分析

4.1、迭代的实现方式如下

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

从上面代码可知循环会执行n-1次,所以复杂度为O(n-1),忽略常数,所以复杂度为O(n)。

4.2、递归的实现方式如下

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

当n=5时,具体的执行如下图:


image.png

从上图可知递归方式的复杂度为O(2^n)。
所以递归方式实现的执行效率是远低于迭代方式的。

5、多数据规模的复杂度

上面我们举的例子都是单个数据规模的,下面看下多数据规模的复杂度如何表示。

public static void test(int n, int k) {
    for (int i = 0; i < n; i++) {
        System.out.println(i + "");
    }
    for (int j = 0; j < k; j++) {
        System.out.println(j + "");
    }
}

上面代码中有两个数据规模:n和k,其复杂度为O(n+k)。

相关文章

  • 时间复杂度(下)

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

  • 复杂度分析

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

  • 复杂度分析笔记

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

  • 常用的排序算法

    插入排序 复杂度 思路 希尔排序 复杂度 思路 选择排序 复杂度 思路 归并排序 复杂度 思路 快速排序复杂度 思...

  • NLP初学之-算法复杂度

    算法的复杂度分为:时间复杂度和空间复杂度。

  • 算法基础知识

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

  • 数据结构-0-时间复杂度和空间复杂度

    1. 算法的复杂度: 算法的复杂度分为时间复杂度和空间复杂度。时间复杂度,是衡量算法执行时间的长度;空间复杂度,是...

  • 时间复杂度和空间复杂度笔记

    复杂度分析笔记 复杂度主要分为时间和空间复杂度 时间复杂度:算法(程序)执行的时间变化趋势 空间复杂度:算法(程序...

  • 算法复杂度

    算法的复杂度是以什么来度量的? 算法的复杂度是以时间复杂度和空间复杂度来计算的。 ①算法的时间复杂度 ...

  • sort_algorithm

    排序方法 时间复杂度(平均) 时间复杂度(最坏) 时间复杂度(最好) 空间复杂度 稳定性 复...

网友评论

      本文标题:复杂度

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