一、算法复杂度

目录

时间复杂度

空间复杂度


算法复杂度旨在计算在输入数据量 N 的情况下,算法的「时间使用」和「空间使用」情况;体现算法运行使用的时间和空间随「数据大小 N 」而增大的速度。

算法复杂度主要可从 时间 、空间 两个角度评价:

  • 时间: 假设各操作的运行时间为固定常数,统计算法运行的「计算操作的数量」 ,以代表算法运行所需时间;
  • 空间: 统计在最差情况下,算法运行所需使用的「最大空间」;

「输入数据大小 N 」指算法处理的输入数据量;根据不同算法,具有不同定义,例如:

  • 排序算法: N 代表需要排序的元素数量;
  • 搜索算法: N 代表搜索范围的元素总数,例如数组大小、矩阵大小、二叉树节点数、图节点和边数等;

时间复杂度

根据定义,时间复杂度指输入数据大小为 N 时,算法运行所需花费的时间。需要注意:

  • 统计的是算法的「计算操作数量」,而不是「运行的绝对时间」。计算操作数量和运行绝对时间呈正相关关系,并不相等。算法运行时间受到「编程语言 、计算机处理器速度、运行环境」等多种因素影响。例如,同样的算法使用 Python 或 C++ 实现、使用 CPU 或 GPU 、使用本地 IDE 或力扣平台提交,运行时间都不同。
  • 体现的是计算操作随数据大小 N 变化时的变化情况。

根据输入数据的特点,时间复杂度具有「最差」、「平均」、「最佳」三种情况,分别使用 O , Θ , Ω 三种符号表示。

根据从小到大排列,常见的算法时间复杂度主要有:

O(1) < O(logN) < O(N) < O(NlogN) < O(N^2) < O(2^N) < O(N!)

常数 O(1) :运行次数与 N 大小呈常数关系,即不随输入数据大小 N 的变化而变化。

线性 O(N) :运行次数与 N 大小呈线性关系,时间复杂度为 O(N) 。

平方 O(N^2) :两层循环相互独立,都与 N 呈线性关系,因此总体与 N 呈平方关系,时间复杂度为 O(N^2) 。

指数 O(2^N) :生物学科中的 “细胞分裂” 即是指数级增长。初始状态为 11 个细胞,分裂一轮后为 22 个,分裂两轮后为 4 个,……,分裂 N 轮后有 2^N 个细胞。算法中,指数阶常出现于递归。

阶乘 O(N!) :阶乘阶对应数学上常见的 “全排列” 。即给定 N 个互不重复的元素,求其所有可能的排列方案,则方案数量为:N×(N−1)×(N−2)×⋯×2×1=N!  阶乘常使用递归实现,算法原理:第一层分裂出 N 个,第二层分裂出 N−1个,…… ,直至到第 N 层时终止并回溯。

对数 O(logN) :对数阶与指数阶相反,指数阶为 “每轮分裂出两倍的情况” ,而对数阶是 “每轮排除一半的情况” 。对数阶常出现于「二分法」、「分治」等算法中,体现着 “一分为二” 或 “一分为多” 的算法思想。

线性对数 O(NlogN) :两层循环相互独立,第一层和第二层时间复杂度分别为 O(logN) 和 O(N) ,则总体时间复杂度为O(NlogN) ;线性对数阶常出现于排序算法,例如「快速排序」、「归并排序」、「堆排序」等。


空间复杂度

空间复杂度涉及的空间类型有:

  • 输入空间: 存储输入数据所需的空间大小;
  • 暂存空间: 算法运行过程中,存储所有中间变量和对象等数据所需的空间大小;
  • 输出空间: 算法运行返回时,存储输出数据所需的空间大小;

通常情况下,空间复杂度指在输入数据大小为 N 时,算法运行所使用的「暂存空间」+「输出空间」的总体大小

而根据不同来源,算法使用的内存空间分为三类:

  • 指令空间:编译后,程序指令所使用的内存空间。
  • 数据空间:算法中的各项变量使用的空间,包括:声明的常量、变量、动态数组、动态对象等使用的内存空间。
  • 栈帧空间:程序调用函数是基于栈实现的(🤔️???),函数在调用期间,占用常量大小的栈帧空间,直至返回后释放。(返回后就释放空间)。算法中,栈帧空间的累计常出现于递归调用。通过递归调用,会同时存在 N 个未返回的函数 ,此时累计使用 O(N) 大小的栈帧空间。

通常情况下,空间复杂度统计算法在 “最差情况” 下使用的空间大小,以体现算法运行所需预留的空间量,使用符号 O 表示。最差情况包含了两层含义,分别为「最差输入数据」情况、算法运行中的「最差运行点」情况。(总之,要考虑到最坏情况,预留出最充分的空间)

根据从小到大排列,常见的算法空间复杂度有:

O(1) < O(logN) < O(N) < O(N^2) < O(2^N)

常数 O(1) :普通常量、变量、对象、元素数量与输入数据大小 N 无关的集合,皆使用常数大小的空间。

线性 O(N) :元素数量与 N 呈线性关系的任意类型集合(常见于一维数组、链表、哈希表等),皆使用线性大小的空间。

平方 O(N^2) :元素数量与 N 呈平方关系的任意类型集合(常见于矩阵),皆使用平方大小的空间。

指数 O(2^N) :指数阶常见于二叉树、多叉树。

对数 O(logN) :对数阶常出现于分治算法的栈帧空间累计、数据类型转换等。


时空权衡
对于算法的性能,需要从时间和空间的使用情况来综合评价。优良的算法应具备两个特性,即时间和空间复杂度皆较低。而实际上,对于某个算法问题,同时优化时间复杂度和空间复杂度是非常困难的。降低时间复杂度,往往是以提升空间复杂度为代价的,反之亦然。

由于当代计算机的内存充足,通常情况下,算法设计中一般会采取「空间换时间」的做法,即牺牲部分计算机存储空间,来提升算法的运行速度。

更多具体实例讲解来自:

作者:Krahets
链接:https://leetcode.cn/leetbook/read/illustration-of-algorithm/r84gmi/
来源:力扣(LeetCode)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值