python数据结构与算法-06_算法分析

news2025/1/9 14:33:11

算法复杂度分析

前面我们说了很多次时间复杂度是 O(1), O(n) 啥的,并没有仔细讲解这个 O 符号究竟是什么。
你可以大概理解为操作的次数和数据个数的比例关系。比如 O(1) 就是有限次数操作,O(n) 就是操作正比于你的元素个数。
这一章我们用更严谨的方式来定义它。

大 O 表示法

我们从一个计算矩阵的例子来引入,这里我参考了 《Data Structures and Algorithms in Python》 中给的一个例子:

考虑计算一个 n * n 矩阵所有元素的和(如果你不知道矩阵,就理解为一个二维数组):

[ 0 1 2 3 4 5 6 7 8 ] \begin{bmatrix} 0 & 1 & 2 \\ 3 & 4 & 5 \\ 6 & 7 & 8 \\ \end{bmatrix} 036147258

这里列举两种方式:

# version1
total_sum = 0
for i in range(n):
    row_sum[i] = 0
    for j in range(n):
        row_sum[i] = row_sum[i] + matrix[i, j]
        total_sum = total_sum + matrix[i, j]

# version2
total_sum = 0
for i in range(n):
    row_sum[i] = 0
    for j in range(n):
        row_sum[i] = row_sum[i] + matrix[i, j]
    total_sum = total_sum + row_sum[i]    # 注意这里和上边的不同

v1 版本的关键操作在 j 循环里,两步加法操作,由于嵌套在第一个循环里,操作步骤是 $ (2n) * n = 2n^2 $。

v2 版本的 total_sum 只有 n 次操作,它的操作次数是 $ n + n*n = n^2 + n $。

这里你可能还感觉不到它们有多大差别,因为计算机执行的太快了,但是当 n 增长特别快的时候,总的操作次数差距就很明显了:

n$ 2n^2 $$ n^2 +n $
10200110
10020,00010,100
10002,000,0001,001,000
10000200,000,000100,010,000
10000020,000,000,00010,000,100,000

通常我们不太关注每个算法具体执行了多少次,而更关心随着输入规模 n 的增加,算法运行时间将以什么速度增加。为此计算机科学家定义了一个符号,
用来表示在最糟糕的情况下算法的运行时间,大 O 符号,在数学上称之为渐进上界(《算法导论》)。

如何计算时间复杂度

上边我们列举了两个版本的计算矩阵和的代码,你看到了两个公式:

  • v1: $ 2n*n = 2n^2 $
  • v2: $ n + n*n = n + n^2 $

当 n 非常大的时候,$ n^2 $ 的数值这里将占主导,我们可以忽略 n 的影响

  • v1: $ 2n*n = 2n^2 $
  • v2: $ n + n*n = n + n^2 \leq 2n^2 $

这里我们可以认为两个算法的时间复杂度均为 $ O(n^2) $

常用时间复杂度

这里我们列举一些常用的时间复杂度,按照增长速度排序,日常我们的业务代码中最常用的是指数之前的复杂度,指数和阶乘的增长速度非常快,
当输入比较大的时候用在业务代码里是不可接受的。

O名称举例
1常量时间一次赋值
log ⁡ n \log n logn对数时间折半查找
n n n线性时间线性查找
n log ⁡ n \log n logn对数线性时间快速排序
n 2 n^2 n2平方两重循环
n 3 n^3 n3立方三重循环
2 n 2^n 2n指数递归求斐波那契数列
n ! n! n!阶乘旅行商问题

空间复杂度

相比时间复杂度,空间复杂度讨论比较少。因为用户老爷等不及,况且现在存储越来越白菜价了,更多时候我们为了提升响应速度宁可多 使用点空间。
空间复杂度相对好算一些,就是每个元素的空间占用乘以总的元素数,有些算法需要额外的空间存储,有些可以本地解决。
如果能本地搞定的我们成为 in place 的,原地操作,比如交换一个 数组中的某两个位置的元素。但是有些操作可能就需要申请额外的空间
来完成算法了,后边我们介绍排序算法的时候会讲到。

常见复杂度增长趋势图

为了让你有个直观的感觉,我们来看看一些经典的时间复杂度和对应的增长趋势图,不同函数在输入规模增长的时候很快就会有巨大的增长差异

在这里插入图片描述

时间换空间,空间换时间

有一些时候时间和空间两者不可兼得,我们会牺牲其中之一来换取另一个。

空间换时间:比如典型的就是 python 中的集合(后面会讲到它的实现原理),虽然它比较浪费空间,但是却能用 O(1)
的时间复杂度来判重。

时间换空间:当我们空间不够用,典型的就是缓存失效算法,我们不可能缓存下无限容量的数据,就会使用一些缓存淘汰算法来保证空间可用。

思考题

  • 回头看看前几章我们讲到的数据结构,以及每个操作的时间复杂度,你能理解了吗?
  • 二分查找是针对有序元素的一种经典的查找算法,你知道的它的时间复杂度吗?你能简单证明下吗。
  • 斐波那契数列你肯定很熟悉,它的公式是 F(n) = F(n-1) + F(n-2),你知道计算一个斐波那契数 F(n)
    的时间复杂度吗?你会用数学公式证明吗?
  • 你能指出时间和空间权衡的例子吗?往往很多高效的数据结构能同时兼顾时间和空间复杂度,但是有时候我们却得做出一定的权衡

参考资料

如果你对数学感兴趣,建议你阅读《算法导论》『函数的增长』这一节 和《Data Structures and Algorithms in Python》第4章。

(本章我用了 MathJax 来书写一些简单的数学公式,使用 "$"包含起来的就是数学公式)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1232622.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

以makefile的方式在linux上编译代码(小白级别)

作者:爱塔居 作者简介:大四学生,分享自己的学习片段~ 目录 前言 一、创建主要文件 二、makefile 前言 多有不足,以供参考,欢迎大佬们指点。我是在虚拟机上执行的,应该都一样。我用的VirtualBox,…

PHP/Lerv通过经纬度计算距离获取附近商家

实际开发中,常常需要获取用户附近的商家,思路是 获取用户位置(经纬度信息)在数据库中查询在距离范围内的商家 注: 本文章内计算距离所使用地球半径统一为 6378.138 km public function mpa_list($latitude,$longitude,$distance){// $latitude 34.306465;// $longitude 10…

Redis篇---第十一篇

系列文章目录 文章目录 系列文章目录前言一、说说Redis持久化机制二、缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题三、热点数据和冷数据是什么前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章…

Android WMS——输入系统管理(十七)

一、简介 1、工作原理 输入子系统从驱动文件中读取事件后,再封装提交给 IMS,IMS 再发送给 WMS 进行处理。 Android 输入系统的工作原理概括来说,内核将原始事件写入到设备节点中,InputReader 不断地通过 EventHub 将原始事件取出来并翻译加工成 Android 输入事件,…

抖音电商双11官方数据最全汇总!

11月13日,抖音电商数据发布“抖音商城双11好物节”数据报告,展现双11期间平台全域经营情况及大众消费趋势。 报告显示,10月20日至11月11日,抖音电商里的直播间累计直播时长达到5827万小时,挂购物车的短视频播放了1697亿…

引入 requests.codes 模块

在网络应用开发中,处理HTTP请求状态码是一项常见的任务。然而,使用Python的requests库时,我们会发现一个不便之处:requests库没有提供一个方便的方式来管理和引用HTTP请求状态码。 在使用requests库进行HTTP请求时,我…

jenkins传参给robotframework

在做自动化的时候,需要使用jenkins传参给rf,rf根据传来的变量运行,在将变量传递给py脚本文件。特此记录。 一、配置jenkins 构建的命令使用如下格式即可(注意空格): cd D:\xxx\test call pybot --variabl…

【数据结构】【版本2.0】【树形深渊】——二叉树入侵

目录 引言 一、树的概念与结构 1.1 树的概念 1.2 树的相关概念 1.3 树的表示 1.4 树在实际中的运用 二、二叉树的概念与结构 2.1 二叉树的概念 2.2 特殊二叉树 满二叉树 完全二叉树 2.3 现实中的二叉树 2.4 二叉树的性质 2.5 二叉树的存储结构 顺序存储 链式…

这篇文章带你了解:如何一次性将Centos中Mysql的数据快速导出!!!

目录 一.数据库导出 1.首先创建文件以.sql结尾的文件 2.打开名mysq的解压目录,导出数据 3.然后在查看即可 4 需要的软件 MobaXterm 一.数据库导出 1.首先创建文件以.sql结尾的文件 通过 touch ssm.sql (小编) 实际上&#xff1a…

提升办公效率,畅享多功能办公笔记软件Notion for Mac

在现代办公环境中,高效的笔记软件对于提高工作效率至关重要。而Notion for Mac作为一款全能的办公笔记软件,将成为你事业成功的得力助手。 Notion for Mac以其多功能和灵活性而脱颖而出。无论你是需要记录会议笔记、管理项目任务、制定流程指南&#xf…

光谱图像超分辨率综述

光谱图像超分辨率综述 简介 ​ 论文链接:A Review of Hyperspectral Image Super-Resolution Based on Deep Learning UpSample网络框架 1.Front-end Upsampling ​ 在Front-end上采样中,是首先扩大LR图像,然后通过卷积网络对放大图像进行…

Linux安装rabbitMq(亲测可用)解决只能本地访问的问题

安装er https://blog.csdn.net/laterstage/article/details/131513793?spm1001.2014.3001.5501下载mq wget --content-disposition "https://packagecloud.io/rabbitmq/rabbitmq-server/packages/el/7/rabbitmq-server-3.10.0-1.el7.noarch.rpm/download.rpm?distro_v…

阿里云4核8G服务器优惠价格表,最低价格501.90元6个月、983.80元1年

阿里云4核8G服务器优惠价格表,云服务器ECS计算型c7实例4核8G配置3M带宽40GB ESSD云盘(系统盘)叠加使用优惠券后价格501.90元6个月、983.80元1年,现在购买经济型e、通用算力型u1、计算型c7和计算型c8a与c8i实例4核8G配置均有优惠&a…

synchronized锁膨胀过程

轻量级锁: 使用场景:如果一个对象虽然有多线程要加锁,但加锁的时间是错开的(也就是没有竞争),那么可以 使用轻量级锁来优化。 轻量级锁原理 1.创建锁记录(Lock Record)对象&#…

IF:9.0+期刊被踢除,11月SCI/SSCI期刊目录已更新!

【SciencePub学术】2023年11月20日,科睿唯安更新了Web of Science核心期刊目录。 继上次SCI期刊目录和SSCI期刊目录更新之后,本次11月更新共有5本期刊发生变动: • SCIE:有5本期刊不再被SCIE期刊目录收录,1本SCIE期刊更…

infercnv 三回首:深入理解infercnv为何能发nature

大家好,不知你是否还记得,前两次关于infercnv的介绍。请看这里: 肿瘤单细胞转录组拷贝数分析结果解读和应用 单细胞拷贝数变异 infercnv再回首 如果下载了示例数据,并且你已经跑了上述代码,不难得到这张图&#xff1…

海外服务器相较于国内服务器有何特点?亚马逊海外服务器为何零跑全球

随着数字时代的迅猛发展,云计算基础设施的重要性愈发凸显。在这个信息爆炸的全球化时代,很多企业的海外业务的成功往往取决于是否拥有安全、可靠、高性能、可扩展、灵活且全球覆盖的云基础设施,因此对很多企业来说,选择一款优质的…

基于STM32设计的(无人)智慧超市-2023改进版

改进的内容: 增加了一个智慧超市登录入口,整个上位机只有一个APP文件。 可以选择顾客或者管理员的身份进去。优化了界面的显示。 一、项目背景 智慧超市是一种新型的零售形式,它将人工智能、物联网、云计算等技术应用到超市运营中,为消费者提供更加便捷、快捷、个性化的购…

X2Keyarch迁移工具实战 | 将CentOS高效迁移至浪潮云峦操作系统KeyarchOS

X2Keyarch迁移工具实战 | 将CentOS高效迁移至浪潮云峦操作系统KeyarchOS 1. 搭建仿真线上业务环境2. 安装KeyarchOS操作系统和X2Keyarch迁移工具3. 将CentOS系统业务迁移至KeyarchOS系统 浪潮信息云峦操作系统KeyarchOS基于Linux Kernel、OpenAnolis等开源技术自主研发的一款服…

Java Enumeration 接口

Java Enumeration 接口 这段代码展示了如何使用 Enumeration 接口来遍历 Properties 对象的键。在这里,foo.getProp() 返回一个 Properties 对象,而 propertyNames() 方法返回一个 Enumeration 对象,它包含了 Properties 对象中所有键的枚举。…