• 如何判断程序的复杂程度:时间和空间复杂度


    1. 时间复杂度:
    使用大O表示法来表示程序的时间复杂度

    常见的7种时间复杂度(复杂度由低到高排序)

    O(1):常数时间复杂度

    O(log(n): 对数时间复杂度

    O(n): 线性时间复杂度

    O(n^2):平方时间复杂度

    O(n^3):立方时间复杂度

    O(k^n):指数时间复杂度,k表示常数

    O(n!):阶乘时间复杂度

    ps:

    这里我们并不考虑前边的系数;O(1) 并不表示复杂度为1,也可以 是2、3等常数;O(n)表示程序运行了n次或者2n、3n次;以此类推其他时间复杂度

    时间复杂度的判断,以一段代码的最高复杂度为准;

    如何判断一段代码的时间复杂度
    简而言之就是看内部某段代码的执行次数

    O(1):常数复杂度

    int n = 1;
    System.out.println(n);
    1
    2
    int n = 1;
    System.out.println(n);
    System.out.println(n+1)
    System.out.println(n+2)
    1
    2
    3
    4
    O(n):线性时间复杂度

    for (int j = 0; j < n; j++) {
    System.out.println(j);
    }
    1
    2
    3
    for (int i = 0; i < n; i++) {
    System.out.println(i);
    }
    for (int j = 0; j < n; j++) {
    System.out.println(j);
    }
    1
    2
    3
    4
    5
    6
    O(n^2):平方时间复杂度

    for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
    System.out.println(i + j);
    }
    }
    1
    2
    3
    4
    5
    O(n^3):立方时间复杂度

    for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
    for (int k = 0; k < n; k++) {
    System.out.println(i + j);
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    O(log(n)): 对数时间复杂度

    这里演示的是以2为底n的对数

    for (int i = 0; i < n; i = i * 2) {
    System.out.println(i);
    }
    1
    2
    3
    O(2^n):指数时间复杂度

    /**
    * 递归求斐波那契数列的第n项;可以通过画运行树的方式获得时间复杂度
    */
    int fib(int n) {
    if (n < 2) return n;
    return fib(n - 1) + fib(n - 2);
    }
    1
    2
    3
    4
    5
    6
    7
    O(n!):阶乘时间复杂度

    todo
    小练习1:求和计算1~n的和
    O(n)

    int y = 2;
    for (int i = 0; i < n; i++) {
    y+=i;
    }
    1
    2
    3
    4
    O(1)

    使用了求和公式:sum = n(n+1)/2

    int y = 2;
    for (int i = 0; i < n; i++) {
    y+=i;
    }
    1
    2
    3
    4
    小练习2:求斐波那契数列
    O(2^n):

    int fib(int n) {
    if (n < 2) return n;
    return fib(n - 1) + fib(n - 2);
    }
    1
    2
    3
    4
    O(n):该方法比递归要快得多

    int fib2(int n) {
    if (n == 1 || n == 2) {
    return 1;
    }
    int a = 1, b = 1, result = 0;
    for (int i = 3; i <= n; i++) {
    result = a + b;
    a = b;
    b = result;
    }
    return result;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    主定理
    主定理(英语:master theorem)提供了用渐近符号(大O符号)表示许多由分治法得到的递推关系式的方法

    常用算法中的应用
    算法 递回关系式 运算时间
    二分搜寻算法
    二叉树遍历
    最佳排序矩阵搜索(已排好序的二维矩阵)
    合并排序
    所有排序的最优算法都是O(nlog(n))

    2. 空间复杂度
    如何判断一段代码的空间复杂度
    主要通过两部分进行判断:

    数组的长度

    如果代码中应用了数组,那么数组的长度,基本上就是空间复杂度;
    e:一维数组的空间复杂度是O(n);二维数组的空间复杂度是O(n^2)

    递归的深度

    如果代码中有递归,那么递归的深度,就是代码的空间复杂度的最大值

    ps:如果代码中既有数组,又有递归,那么两者的最大值就是代码的空间复杂度

    leecode有个爬楼梯的复杂度分析情况;可以进行练习

    3. 数组和链表的时间复杂度分析
    数组
    随机增加:O(n)
    随机查询:O(1)
    随机删除:O(n)

    链表
    随机增加:O(1)
    随机查询:O(n)
    随机删除:O(1)

    跳表
    跳跃表(skiplist)是一种随机化的数据, 由 William Pugh 在论文《Skip lists: a probabilistic alternative to balanced trees》中提出, 跳跃表以有序的方式在层次化的链表中保存元素, 效率和平衡树媲美 —— 查找、删除、添加等操作都可以在对数期望时间下完成, 并且比起平衡树来说, 跳跃表的实现要简单直观得多。

    简单来说,跳跃表是有序链表的一种扩展,在有序列表的基础上进行了升维处理

    ------ 往事如烟,伴着远去的步伐而愈加朦胧。未来似雾,和着前进的风儿而逐渐清晰!
  • 相关阅读:
    vue+springboot+element+vue-resource实现文件上传
    使用bfg快速清理git历史大文件
    git clone异常 【fatal: protocol error: bad line length character: Inte】
    excel 一次删除所有空行
    vim编辑器
    prometheus安装
    递归计算分波那契数列和阶乘
    如何理解线程安全?
    创建线程的方式
    为什么说一个对象是线程安全的?
  • 原文地址:https://www.cnblogs.com/cutesnow/p/14658079.html
Copyright © 2020-2023  润新知