【Python 数据结构 2.时间复杂度和空间复杂度】
Life is a journey
—— 25.2.28
一、引例:穷举法
1.单层循环
所谓穷举法,就是我们通常所说的枚举,就是把所有情况都遍历了的意思。
例:给定n(n ≤ 1000)个元素ai,求其中奇数有多少个
判断一个数是偶数还是奇数,只需要求它除上2的余数是0还是1,那么我们把所有数都判断一遍,并且对符合条件的情况进行计数,最后返回这个计数器就是答案,这里需要遍历所有的数,这就是穷举
def JudgeNum(self, n: int, a: List[int]) -> int:count = 0for i in range(n):if a[i] % 2 == 1:count += 1return count
时间复杂度 O(n)
2.双层循环
例2:给定n(n ≤ 1000)个元素ai,求有多少个二元组(i,j),满足ai + aj是奇数(i < j)。
def JudgeNum(self, n: int, a[]: List[int]) -> int: count = 0for i in range(n):for j in range(i + 1, n):if (a[i} + a[j]) % 2 == 1:count += 1return count
时间复杂度 O(n^2)
3.三层循环
例3:给定n(n ≤ 1000)个元素ai,求有多少个三元组(i,j,k),满足ai + aj + ak是奇数(i < j < k)。
def JudgeNum(self, n: int, a: list[int]) -> int:count = 0for i in range(n):for j in range(i + 1, n):for k in range(j + 1, n):if (a[i] + a[j] + a[k]) % 2 == 1:count += 1return count
时间复杂度 O(n^3)
随着循环嵌套的越多,时间消耗会越来越多,并且三个循环是乘法的关系,也就是遍历次数随着n的增加,呈现立方式的增长
4.递归枚举
例:给定n(n ≤ 1000)个元素ai 和 一个整数 k(k ≤ n),求有多少个有序k数组,满足他们的和是偶数
我们需要根据k的不同,决定写几层循环,k的最大值为1000,也就意味着我们要写1000个if-else语句,显然,这样是无法接受的,比较暴力的做法是采用递归
二、时间复杂度
1.时间复杂度的表示法
在进行算法分析时,语句总的执行次数 T(n) 是关于问题规模 n 的函数,进而分析 T(n) 随着 n 的变化情况而确定 T(n) 的数量级
算法的时间复杂度,就是算法的时间度量,记作:T(n)=O(f(n)) 用大写的 O 来体现算法时间复杂度的记法,我们称之为:大 O 记法
Ⅰ、时间函数
时间复杂度往往会联系到一个函数,自变量:表示规模,应变量:表示执行时间。
这里所说的执行时间,是指广义的时间,也就是单位并不是"秒"、"毫秒"这些时间单位,它代表的是一个"执行次数"的概念。我们用 f(n) 来表示这个时间函数。
Ⅱ、经典函数举例
在例1中,我们接触到了单层循环,这里的 n 是一个变量,随着 n 的增大,执行次数增大,执行时间就会增加,所以就有了时间函数的表示法如下:f(n) = n

这就是经典的线性时间函数
在例2中,我们接触到了双层循环,它的时间函数表示法如下:f(n) = n * (n - 1) / 2

这是一个平方级别的时间函数
在例3中,我们接触到了三层循环,它的时间函数表示法如下:f(n) = n * (n - 1) * (n - 2) / 6

这是一个立方级别的时间函数
2.时间复杂度
一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。
并且我们有一个更加优雅的表示法,即:T(n)=O(f(n)),其中 O 念成 大O
1) 当 f(n) = n,我们称这个算法拥有线性时间复杂度,记作 O(n);
2) 当 f(n) = n * (n-1) / 2,我们称这个算法拥有平方级时间复杂度,记作 O(n^2);
3) 当 f(n) = n * (n-1) * (n-2) / 6,我们称这个算法拥有立方级的时间复杂度,记作 O(n^3);
这时候我们发现,f 的函数可能很复杂,但是 O 表示的函数往往比较简单,它舍弃了一些"细节“
3.高阶无穷小
如果 lim(β / α) = 0,则称 ”β 是比 α较高阶的无穷小“
例:f(n) = n * (n - 1) / 2
共两部分组成,一部分是 n ^ 2 的部分,另一部分是 n 的部分,显而易见,一定是 n ^ 2,相对于 n ^ 2 来说,n 可以忽略不计
随着 n 的增长,线性的部分增长已经跟不上平方部分,这样,线性部分的时间消耗相对于平方部分来说已经”微不足道“,所以我们直接忽略,于是就有时间复杂度表示如下:
T(n) = O(f(n))
= O(1/2 * n ^ 2 - 1 / 2 * n)
= O(1/2 * n ^ 2)
= O(n ^ 2)
所以,它的时间复杂度就是O(n ^ 2)了
4.简化系数
发现上述的公式推到的过程中,将 n ^ 2 前面的系数 1/2 去掉了,这是由于 时间复杂度描述的更多的是一个数量级,所以尽量减少干扰项,对于两个不同的问题,可能执行时间不同,但是我们可以说他们的 时间复杂度 是一样的
三、常见的时间复杂度
1.常数阶
max = 1024
def getMax() -> int:return max
没有循环,是常数时间,表示为O(1)
2.对数阶
例4:给定n(n ≤ 10000)个元素的有序数组 ai 和 整数 v,求 v 在数组中的下标,不存在则输出 -1
这个问题是一个常见的查询问题,我们可以用O(n)的算法遍历整个数组,然后去找 v 的值
当然,也有更快的方法,注意到题目中的条件,数组 ai 是有序的,所以我们可以利用二分查找来实现
def bin(n: int, a: List[int], v:int) -> int:left = 0,right = n - 1mid = 0while left <= right:mid = (left + right) // 2if a[mid] < v:left = v + 1elif a[mid] > v:right = v - 1else:return midreturn -1
这是一个二分查找的实现,时间复杂度为O(logn)
每次相当于把n切半,即:
n -> n / 2 -> n / 4 -> … -> n / 2 ^ k -> … -> 0
f(n) = O(n) = O(k) = O(logn)
3.根号阶
例5:给定一个数 n(n ≤ 10 ^ 9),问 n 是否是一个素数(素数的概念:除了1和它本身,没有其他因子)
基于素数的概念,我们可以枚举所有 i 属于[2, n),看能否整除 n,一旦能整除,代表找到了一个银子,则不是素数,当所有数枚举完还没找到,他就是素数
但是这样做,显然效率太低,我们进行一些思考,得到如下算法:
import mathdef isPrime(n: int) -> bool:if n <= 1:return Falsesqrtn = math.sqrt(n)for i in range(2, sqrtn + 1):if n % i == 0:return Falsereturn True
这个算法的时间复杂度为:O(根号n)
为什么只需要枚举 根号n 以内的数呢?
因为一旦有一个因子 s,必然有另一个因子 n / s,它们之间必然有一个大小关系,无论是 s ≤ n / s,还是 n / s ≤ s,都能通过两边乘上 s 得出:![]()
比根号n小的数中,如果没有这样一个因子,则比根号n大的数中也不会存在这样一个因子
4.线性阶
例1中,我们接触到了单层循环,这里的 n 是一个变量,随着 n 的增大,执行次数增大,执行时间就会增加,所以就有了时间函数的表示法如下:f(n) = n
5.线性对数阶
例6:给定n(n ≤ 100000)个元素 ai,求满足 ai + aj = 1024 的有序二元组(i, j)有多少对
我们可以先对所有元素 ai 按照递增排序,然后枚举 ai,并且在[i + 1, n)范围内查找是否存在 ai + aj = 1024
def Find(n: int, a: List[int]) -> int:count = 0sort(a)for i in range(n):j = 1024 - a[i]left, right = i + 1, n - 1while left <= right:mid = left + (right - left) // 2if a[mid] == target:count += 1breakelif a[mid] < taegrt:left = mid + 1else:right = mid - 1return count
f(n) = O(n * logn) = O(nlogn)
6.多项式阶
多项式的含义是函数 f(n) 可以表示成如下形式:![]()
所以 O(n^5)、O(n^4)、O(n^3)、O(n^2)、O(n)都是多项式时间
7.指数阶
例7:给出n(n ≤ 15)个点,以及每两个点之间的关系(连通还是不连通),求一个最大的集合,使得在这个集合中都连通
这是求子集的问题,由于最多只有 15 个点,我们就可以枚举每个点选或者不选,总共 2^n 种情况,然后再判断是否满足题目中的连通性,这个算法时间复杂度为 O(n ^ 2 * 2 ^ n);
8.阶乘阶
例8:给定n(n ≤ 12)个点,并且给出任意两点间的距离,求从 s 点开始经过所有点回到 s 点的距离的最小值
这个问题就是典型的暴力枚举所有情况求解,可以把这些点当成是一个排列,所以排列方案数为: n!
四、如何判断时间复杂度
1.标准
首先,我们需要一个标准,也就是总的执行次数多少合适
我们把其定义为 S = 10 ^ 6
2.问题规模
有了标准以后,我们还需要知道问题规模,也就是O(n)中的n
3.套公式
然后就是凭感觉套公式了
当 n < 12 时,可能是需要用到阶乘级别的算法,即 O(n!)
当 n < 16 时,可能是需要状态压缩的算法,比如 O(n ^ 2)、O(n * 2 ^ n)、O(n ^ 2 * 2 ^ n)
当 n < 30 时,可能是需要 O(n ^ 4)的算法,因为 30 ^ 4 差不多接近 10 ^ 6
当 n < 100 时,可能是需要 O(n)的算法,因为 1003= 106
当n < 1000 时,可能是需要 O(n ^ 2)的算法,因为 1000 ^ 2 = 10 ^ 6
当n < 100000 时,可能是需要 O(n * log2n)、O(n * (log2n) ^ 2)的算法
当n < 1000000 时,可能是需要 O(根号n)、O(n)的算法
五、空间复杂度
空间复杂度是指算法在执行过程中所需的额外存储空间。这包括算法在运行时使用的变量、数组、链表 等数据结构所占用的内存空间。它和算法的时间复杂度一起,是衡量算法性能的重要指标之一。
在算法设计中,我们通常希望尽可能地降低空间复杂度,以减少内存的使用,提高算法的效率。然而,在某些情况下,为了实现算法的功能,可能需要使用更多的存储空间。
六、常见数据结构的空间复杂度
1.顺序表:O(n),其中 n 是顺序表的长度
2.链表:O(n),其中 n 是链表的长度
3.栈:O(n),其中 n 是 栈的最大深度
4.队列:其中 n 是队列的最大长度
5.哈希表:O(n),其中 n 是哈希表中元素的数量
6.树:O(n),其中 n 是树的节点数量
7.图:O(n + m),其中 n 是图中顶点的数量,m 是图中边的数量
七、空间换时间
通常使用额外空间的目的,就是为了换取时间上的效率,也就是我们常说的 空间换时间。
最经典的空间换时间就是动态规划,例如求一个斐波那契数列的第 n 项的值,如果不做任何优化就是利用循环进行计算,时间复杂度 (n),但是如果引入了数组,将计算结果预先存储在数组中,那么每次询问只需要 O(1) 的时间复杂度就可以得到第 n 项的值,而这时,由于引入了数组所以空间复杂度就变成了 O(n)。
相关文章:
【Python 数据结构 2.时间复杂度和空间复杂度】
Life is a journey —— 25.2.28 一、引例:穷举法 1.单层循环 所谓穷举法,就是我们通常所说的枚举,就是把所有情况都遍历了的意思。 例:给定n(n ≤ 1000)个元素ai,求其中奇数有多少个 判断一…...
【Qt QML】QML鼠标事件(MouseArea)
QML鼠标事件全面解析 一、MouseArea基础概念 在 QML 中,鼠标事件是处理用户与界面元素交互的重要部分。QML 提供了多种方式来处理鼠标事件,MouseArea 是 QML 中用于处理鼠标事件的核心元素,它可以覆盖在其他元素之上,捕获鼠标操作并触发相应的信号。 1、基本用法 import …...
LeetCode 202. 快乐数 java题解
https://leetcode.cn/problems/happy-number/description/ 哈希表 class Solution {public boolean isHappy(int n) {if(n1) return true;HashSet<Integer> setnew HashSet<>();while(n!1&&!(set.contains(n))){//没找到结果;没有重复出现过se…...
《认知·策略·跃迁:新能源汽车工程师的深度学习系统构建指南》
--- ## 前言:为什么传统学习法正在杀死你的竞争力? 在新能源汽车领域,我们正经历着每18个月知识体系更新迭代的指数级变革。当磷酸铁锂电池能量密度刚突破200Wh/kg时,固态电池已进入量产倒计时;当自动驾驶还在L2级徘…...
PHP环境安装达梦数据库驱动实操
PHP环境安装达梦数据库驱动实操 一、环境准备 达梦数据库安装 从达梦官网下载对应系统版本的DM8开发版或企业版,完成安装并确保数据库服务正常运行。安装后需记录数据库的安装路径(如Windows默认路径为D:\dmdbms,Linux为/dm/server࿰…...
Electron + Vite + React + TypeScript 跨平台开发实践指南
Electron Vite React TypeScript 跨平台开发全栈实践指南 开发环境的搭建(node.js,npm的安装)请参见我的文章 2025Q1 核心组件版本矩阵 组件版本关键改进特性Electron30.0.0原生ESM支持、V8引擎性能优化30%Vite6.0.0多核编译加速、SSR增强模式React21.0.0并发…...
Java---入门基础篇(下)---方法与数组
前言 本篇文章主要讲解有关方法与数组的知识点 ,是基础篇的一部分 , 而在下一篇文章我会讲解类和对象的知识点 入门基础篇上的链接给大家放在下面啦 ! Java---入门基础篇(上)-CSDN博客 感谢大家点赞👍🏻收藏⭐评论✍🏻 欢迎各位大佬指点…...
【分布式理论11】分布式协同之分布式事务(一个应用操作多个资源):从刚性事务到柔性事务的演进
文章目录 一. 什么是分布式事务?二. 分布式事务的挑战三. 事务的ACID特性四. CAP理论与BASE理论1. CAP理论1.1. 三大特性1.2. 三者不能兼得 2. BASE理论 五. 分布式事务解决方案1. 两阶段提交(2PC)2. TCC(Try-Confirm-Cancel&…...
【文献阅读】Collective Decision for Open Set Recognition
基本信息 文献名称:Collective Decision for Open Set Recognition 出版期刊:IEEE TRANSACTIONS ON KNOWLEDGE AND DATA ENGINEERING 发表日期:04 March 2020 作者:Chuanxing Geng and Songcan Chen 摘要 在开集识别࿰…...
Gorm中的First()、Create()、Update()、Delete()的错误处理
一. First() result : tx.Model(&models.Attachment{}).Where("home ? AND home_id ?", attachment.Home, attachment.HomeID).First(&existingAttachment)如果没有查询到数据,result.Error的值是什么? 在使用 GORM(…...
【心得】一文梳理高频面试题 HTTP 1.0/HTTP 1.1/HTTP 2.0/HTTP 3.0的区别并附加记忆方法
面试时很容易遇到的一个问题—— HTTP 1.0/HTTP 1.1/HTTP 2.0/HTTP 3.0的区别,其实这四个版本的发展实际上是一环扣一环的,是逐步完善的,本文希望帮助读者梳理清楚各个版本之间的区别,并且给出当前各个版本的应用情况,…...
Navicat连接虚拟机数据库详细教程
Navicat连接虚拟机数据库详细教程 以Windows主机 上的navicat 连接ubuntu虚拟机为例 确认虚拟机ip地址和主机ip地址 主机地址查询 cmd输入ipconfig 登录mysql 创建用户 CREATE USER newuserlocalhost IDENTIFIED BY password; CREATE USER newuser% IDENTIFIED BY passwor…...
委托者模式(掌握设计模式的核心之一)
目录 问题: 举例: 总结:核心就是利用Java中的多态来完成注入。 问题: 今天刷面经,刷到装饰者模式,又进阶的发现委托者模式,发现还是不理解,特此记录。 举例: 老板…...
DeepSeek-R1 论文笔记:通过强化学习提升大语言模型的推理能力
论文标题:DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning 作者团队:DeepSeek-AI 发表时间:2025 前置知识 & 术语 模型蒸馏 语言模型蒸馏的目标是将大型教师模型的知识(如语义理解、上…...
实现Unity shader扭曲效果
实现思路 1、扭曲材质赋于面片 2、抓取当前一帧的图片内容 3、获取屏幕坐标 4、利用屏幕坐标对抓取的图片采样 5、再采样张扰动贴图做扭曲 Shader "Unlit/NewUnlitShader" {Properties {_DistortTex ("扰动贴图 (RGB)", 2D) "bump" {}_Di…...
七星棋牌 6 端 200 子游戏全开源修复版源码(乐豆 + 防沉迷 + 比赛场 + 控制)
七星棋牌源码 是一款运营级的棋牌产品,覆盖 湖南、湖北、山西、江苏、贵州 等 6 大省区,支持 安卓、iOS 双端,并且 全开源。这个版本是 修复优化后的二开版本,新增了 乐豆系统、比赛场模式、防沉迷机制、AI 智能控制 等功能&#…...
C++STL---<limits>
C <limits> 头文件: <limits> 头文件是 C 标准库中用于获取各种数据类型的数值范围、精度等信息的工具。它通过模板类 std::numeric_limits 提供了对基本数据类型(如 int、float、double 等)的详细属性查询功能。通过 std::nume…...
一键安装Mysql部署脚本之Linux在线安装Mysql,脚本化自动化执行服务器部署(附执行脚本下载)
相关链接 一键安装Redis部署脚本之Linux在线安装Redis一键安装Mysql部署脚本之Linux在线安装Mysql一键安装JAVA部署脚本之Linux在线安装JDK一键安装Nginx部署脚本之Linux在线安装NginxNavicat最新版(17)详细安装教程Xshell客户端免费版无需注册XFtp客户端免费版无需注册 前言…...
ES、OAS、ERP、电子政务、企业信息化(高软35)
系列文章目录 ES、OAS、ERP、电子政务、企业信息化 文章目录 系列文章目录前言一、专家系统(ES)二、办公自动化系统(OAS)三、企业资源规划(ERP)四、典型信息系统架构模型1.政府信息化和电子政务2.企业信息…...
文生图开源模型发展史(2014-2025年)
文生图开源模型的发展历程是一段充满技术革新、社区生态繁荣与商业化竞争的多维度演进史。 一、技术萌芽期(2014-2020年) 核心突破 2014年:GAN(生成对抗网络)诞生,首次实现数据驱动式图像生成࿰…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
DeepSeek越强,Kimi越慌?
被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...
路由基础-路由表
本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中,往往存在多个不同的IP网段,数据在不同的IP网段之间交互是需要借助三层设备的,这些设备具备路由能力,能够实现数据的跨网段转发。 路由是数据通信网络中最基…...
DL00871-基于深度学习YOLOv11的盲人障碍物目标检测含完整数据集
基于深度学习YOLOv11的盲人障碍物目标检测:开启盲人出行新纪元 在全球范围内,盲人及视觉障碍者的出行问题一直是社会关注的重点。尽管技术不断进步,许多城市的无障碍设施依然未能满足盲人出行的实际需求。尤其是在复杂的城市环境中ÿ…...
