当前位置: 首页 > news >正文

【数据结构和算法】时间复杂度和空间复杂度

时间复杂度

时间复杂度是算法效率的一个重要指标,它描述了算法运行时间与输入数据量之间的关系,给出了算法运行时间的上界估计。

时间复杂度主要关注算法中基本操作的执行次数,特别是当输入规模(通常用n表示)增大时,这些操作次数的增长趋势。在表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分如果为f(N),那么时间复杂度为O(f(N))。算法的时间复杂度通常为最坏情况下的时间复杂度。下面通过几个例子来说明如何计算时间复杂度:

  • 常数时间复杂度O(1):一个操作如果和样本的数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作。这些操作的时间复杂度被标记为 O(1)。例如赋值操作x=1,不论给x赋值为多少,这个操作的时间都不变。

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

    def linear_time_example(arr):result = 0for i in range(len(arr)):result += arr[i]return result
    

    这个函数遍历数组arr的每一个元素并求和。如果数组长度为n,则循环将执行n次,因此时间复杂度为O(n)O(n)。

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

    def quadratic_time_example(matrix):result = 0for i in range(len(matrix)):for j in range(len(matrix[i])):result += matrix[i][j]return result
    

    在这个例子中,我们有两个嵌套循环,它们都依赖于矩阵的行数(假设矩阵为方阵)。每个循环都将执行n次,所以总的操作次数为n×n=n2,因此时间复杂度为O(n2)。

  • 对数时间复杂度O(logn)

    def binary_search(arr, target):low, high = 0, len(arr) - 1while low <= high:mid = (low + high) // 2if arr[mid] == target:return midelif arr[mid] < target:low = mid + 1else:high = mid - 1return -1
    

    上述代码为二分查找实现,每次迭代,搜索范围都会减半,因此操作次数与输入大小的对数成比例,即时间复杂度为O(log⁡n)。

  • 线性对数时间复杂度O(nlogn)

    归并排序是一个典型的O(nlog⁡n)算法。它将数组分为两半,递归地排序每一半,然后合并两个有序的部分。虽然每个递归调用的时间复杂度为O(n),但由于递归深度为log⁡n,总的时间复杂度为O(nlog⁡n)。

评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间,也就是“常数项时间”。

空间复杂度

空间复杂度是衡量算法在运行过程中所需存储空间的一个指标。它描述了算法消耗的内存与输入数据量之间的关系,通常也使用大O符号(Big O notation)来表示。空间复杂度分析包括了算法运行时临时占用的额外空间,但不包括输入数据本身占用的空间(除非算法需要复制输入数据)。

以下是一些常见的空间复杂度类别:

  1. 常数空间复杂度 - O(1):算法所需的额外空间不随输入数据量的增加而改变。例如,一个简单的函数,仅使用几个变量进行计算,无论输入数据多大,所占空间都是固定的。
  2. 线性空间复杂度 - O(n):算法所需的额外空间直接与输入数据量成正比。例如,在排序算法中,如果需要创建一个与输入数组同样大小的新数组,则空间复杂度为O(n)。
  3. 对数空间复杂度 - O(log⁡n):这种空间复杂度较少见,通常发生在使用分治策略的算法中,如一些递归算法,它们可能只需要存储输入数据的层次结构,而非全部数据。
  4. 平方空间复杂度 - O(n2):如果算法需要创建一个二维数组,且每个维度的大小都与输入数据量相关,那么空间复杂度可能是O(n2)。
  5. 递归算法的空间复杂度:递归算法的空间复杂度通常由递归调用栈的深度决定。例如,二叉树的前序遍历在最坏情况下可能需要O(n)的空间,因为递归调用栈的深度可能达到树的高度。

空间复杂度中最常见的就是O(1)和O(n)。理解空间复杂度对于优化算法和系统设计非常重要,特别是在资源受限的环境中,如嵌入式系统或移动设备。有时候,为了节省空间,可能需要牺牲时间效率,反之亦然。因此,在实际应用中,经常需要在时间和空间之间做出权衡。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • springBoot框架
  • 守护数字堡垒:全面掌握安全配置管理
  • 什么是令牌桶算法?工作原理是什么?使用它有哪些优点和注意事项?
  • C++ | 深入理解C++的IO流:从控制台输出流到文件输出流的应用
  • LeetCode面试题Day8|LeetCode13 罗马数字转整数、LeetCode12 整数转罗马数字
  • Events and the Kernel
  • HarmonyOS NEXT星河版零基础入门(2)
  • 3-2 光敏电阻(智能应用篇)
  • 构建坚不可摧的防线:全面指南到高效信息安全管理体系
  • 力扣第五十六题——合并区间
  • 设计模式-装饰者模式
  • ubuntu创建txt
  • 2024年TI杯E题-三子棋游戏装置方案分享-jdk123团队-第二弹 手搓机械臂
  • 搅拌站智能化改造,数字化管理如何助力降本增效?
  • 走心解答hashCode与equals,尽量说明白
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 【node学习】协程
  • angular2开源库收集
  • classpath对获取配置文件的影响
  • CSS 三角实现
  • CSS3 变换
  • Django 博客开发教程 16 - 统计文章阅读量
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • k8s如何管理Pod
  • MySQL数据库运维之数据恢复
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • Spring声明式事务管理之一:五大属性分析
  • WePY 在小程序性能调优上做出的探究
  • 阿里研究院入选中国企业智库系统影响力榜
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 二维平面内的碰撞检测【一】
  • 区块链将重新定义世界
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 我的业余项目总结
  • 线性表及其算法(java实现)
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • ​如何防止网络攻击?
  • # 计算机视觉入门
  • # 职场生活之道:善于团结
  • #### go map 底层结构 ####
  • #FPGA(基础知识)
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (1)svelte 教程:hello world
  • (2020)Java后端开发----(面试题和笔试题)
  • (Demo分享)利用原生JavaScript-随机数-实现做一个烟花案例
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (六)c52学习之旅-独立按键
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (算法二)滑动窗口
  • ./和../以及/和~之间的区别