【手撕数据结构】卸甲时/空间复杂度
目录
- 前言
- 时间复杂度
- 概念
- ⼤O的渐进表⽰法
- 小试牛刀
- 空间复杂度
前言
要想知道什么是空/时间复杂度,就得知道什么是数据结构。
这得分两层来理解。我们生活中处处存在数据,什么抖音热点上的国际大事,什么懂的都懂的雍正卸甲等等一系列我们用户看得到的,就是抖音存储在后台服务器的数据。但这些数据都有一个特点,那就是都在抖音的热搜榜单上,而这个榜单就是结构,保证数据在一个固定的位置里以便用户浏览。
此外有了数据结构,就离不开算法。那么我们刚刚说了,数据结构是把数据有规律的存储在一个结构中,那么怎么从结构中有效率的存取数据,这就是算法。
时间复杂度
有了算法,就存在时间复杂度和空间复杂度。因为计算机现在的内存越来越大,所以时间复杂度比空间复杂度更显得重要。所以我们先来了解时间复杂度
概念
时间复杂度,最重要的词就是时间,这里的时间就是指一个程序运行时的时间,如果时间复杂度越少,那么证明这个算法越好。时间复杂度计算用函数式T(N)表示
那为什么我们不提前算出这个程序的时间复杂度来写出最优解的代码呢?这里就涉及到计算机的问题。
- 因为程序运⾏时间和编译环境和运⾏机器的配置都有关系,⽐如同⼀个算法程序,⽤⼀个⽼编译
器进⾏编译和新编译器编译,在同样机器下运⾏时间不同。- 同⼀个算法程序,⽤⼀个⽼低配置机器和新⾼配置机器,运⾏时间也不同。
- 并且时间只能程序写好后测试,不能写程序前通过理论思想计算评估。
下面我们来看一段代码:
// 请计算⼀下Func1中count语句总共执⾏了多少
次?
void Func1(int N)
{
int count = 0;
for (int i = 0; i < N ; ++ i)
{
for (int j = 0; j < N ; ++ j)
{
++count;
}
}
for (int k = 0; k < 2 * N ; ++ k)
{
++count;
}
int M = 10;
while (M--)
{
++count;
}
}
这段代码如果根据count的执行次数来看的话应该是:
T (N) = N2 + 2 ∗ N + 10
• N = 10 T(N) = 130
• N = 100 T(N) = 10210
• N = 1000 T(N) = 1002010
这时候有人就说,那个int count=0不算吗;
这里我们就太小看我们的计算机了,我们计算机一秒钟cpu可以执行上亿次,这小小的一次当然可以忽略不计。所以说我们计算的时间复杂度并不准确,只是粗略估计而已,这时候我们就用一个新的符号表示.
⼤O的渐进表⽰法
⼤O符号(Big O notation):是⽤于描述函数渐进⾏为的数学符号;这里用来表示估算的时间复杂度。
那么这里还是跟T(N)一样算吗,如果是这样我们就没必要用另外一个符号来表示了。这里就涉及到算O的规则:
- 时间复杂度函数式T(N)中,只保留最⾼阶项,去掉那些低阶项,因为当N不断变⼤时,低阶项对结果影响越来越⼩,当N⽆穷⼤时,就可以忽略不计了。
- 如果最⾼阶项存在且不是1,则去除这个项⽬的常数系数,因为当N不断变⼤,这个系数对结果影响越来越⼩,当N⽆穷⼤时,就可以忽略不计了
- T(N)中如果没有N相关的项⽬,只有常数项,⽤常数1取代所有加法常数。
那么再来看上面的T(N)=N^ 2 + 2 ∗ N + 10,这里的最高阶是N2所以去掉其他的低阶,复杂度就为(ON^2)
小试牛刀
// 计算Func3的时间复杂度?
void Func3(int N, int M)
{
int count = 0;
for (int k = 0; k < M; ++ k)
{
++count;
}
for (int k = 0; k < N ; ++
k)
{
++count;
}
printf("%d\n", count);
}
这里的T(N)=M+N,那我们再来算O(N),这里M和N都是同阶,所以不符合第一条规则,也没有对应第二条和第三条,所以为o(N+M),那么有人就问了,万一N比M大呢,是不是因该是O(N).这里问题就是,你怎么知道N比M大?万一是M比N大呢,所以保险起见我们都留下来。
// 计算strchr的时间复杂度?
const char * strchr ( const char* str, int character)
{
const char* p_begin = s;
while (*p_begin != character)
{
if (*p_begin == '\0')
return NULL;
p_begin++;
}
return p_begin;
}
这里我们是查找character在str中的位置,这里我补充一个知识点:
- 我们的O算的一般是一个算法的最坏情况下的复杂度
这里就可以分为三个复杂度:
1.最好情况
若要查找的字符在字符串第⼀个位置,则:
F (N) = 1,复杂度为o(1)
2.平均情况:
若要查找的字符在字符串中间位置,则:
F (N) = N/2,O(N/2)
3.最坏情况
若要查找的字符在字符串最后的⼀个位置,则:
F (N) = N,O(N)
// 计算BubbleSort的时间复杂度?
void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i-1] > a[i])
{
Swap(&a[i-1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}
最坏情况下,又因为保留高阶去掉n/2(第一条),忽略系数(第二条),所以为ON^2
void func5(int n)
{
int cnt = 1;
while (cnt < n)
{
cnt *= 2;
}
}
当n=2时,执⾏次数为1
当n=4时,执⾏次数为2
当n=16时,执⾏次数为4
假设执⾏次数为 x ,则 2
x = n
因此执⾏次数: x = log n
因此:func5的时间复杂度取最差情况为:
O(log2 ^n)
不同书籍的表⽰⽅式不同,以上写法差别不⼤,我们建议使⽤ log n
空间复杂度
空间复杂度要注意的是,他的计算表示也是用O来表示,并且他的规则与时间复杂度一样遵守那三条规则
注意
函数运⾏时所需要的栈空间(存储参数、局部变量、⼀些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运⾏时候显式申请的额外空间来确定
例1:
// 计算BubbleSort的时间复杂度?
void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i-1] > a[i])
{
Swap(&a[i-1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}
函数栈帧在编译期间已经确定好了,
只需要关注函数在运⾏时额外申请的空间。
BubbleSort额外申请的空间有
exchange等有限个局部变量,使⽤了常数个额外空间
因此空间复杂度为 O(1)
相关文章:

【手撕数据结构】卸甲时/空间复杂度
目录 前言时间复杂度概念⼤O的渐进表⽰法小试牛刀 空间复杂度 前言 要想知道什么是空/时间复杂度,就得知道什么是数据结构。 这得分两层来理解。我们生活中处处存在数据,什么抖音热点上的国际大事,什么懂的都懂的雍正卸甲等等一系列我们用户看得到的&a…...

消防认证-防火窗
一、消防认证 消防认证是指消防产品符合国家相关技术要求和标准,且通过了国家认证认可监督管理委员会审批,获得消防认证资质的认证机构颁发的证书,消防产品具有完好的防火功能,是住房和城乡建设领域验收的重要指标。 二、认证依据…...

C++进阶-二叉树进阶(二叉搜索树)
1. 二叉搜索树 1.1 二叉搜索树概念 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值2.若它的右子树不为空,则右子树上所有节点的值都大于…...

【Unity小知识】UnityEngine.UI程序集丢失的问题
问题表现 先来说一下问题的表现,今天在开发的时候工程突然出现了报错,编辑器提示UnityEngine.UI缺少程序集引用。 问题分析与解决(一) 既然是程序集缺失,我们首先查看一下工程项目是否引用了程序集。在项目引用中查找一…...

CentOS 离线安装部署 MySQL 8详细教程
1、简介 MySQL是一个流行的开源关系型数据库管理系统(RDBMS),它基于SQL(Structured Query Language,结构化查询语言)进行操作。MySQL最初由瑞典的MySQL AB公司开发,后来被Sun Microsystems公司…...

云计算【第一阶段(28)】DNS域名解析服务
一、DNS解析的定义与作用 1.1、DNS解析的定义 DNS解析(Domain Name System Resolution)是互联网服务中的一个核心环节,它负责将用户容易记住的域名转换成网络设备能够识别和使用的IP地址。一般来讲域名比 IP 地址更加的有含义、也更容易记住…...

pygame 音乐粒子特效
代码 import pygame import numpy as np import pymunk from pymunk import Vec2d import random import librosa import pydub# 初始化pygame pygame.init()# 创建屏幕 screen pygame.display.set_mode((1920*2-10, 1080*2-10)) clock pygame.time.Clock()# 加载音乐文件 a…...

Leetcode 295.数据流的中位数
295.数据流的中位数 问题描述 中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。 例如 arr [2,3,4] 的中位数是 3 。例如 arr [2,3] 的中位数是 (2 3) / 2 2.5 。 实现 MedianFinder 类: Media…...
A59 STM32_HAL库函数 之 TIM扩展驱动 -- A -- 所有函数的介绍及使用
A59 STM32_HAL库函数 之 TIM扩展驱动 -- A -- 所有函数的介绍及使用 1 该驱动函数预览1.1 HAL_TIMEx_HallSensor_Init1.2 HAL_TIMEx_HallSensor_DeInit1.3 HAL_TIMEx_HallSensor_MspInit1.4 HAL_TIMEx_HallSensor_MspDeInit1.5 HAL_TIMEx_HallSensor_Start1.6 HAL_TIMEx_HallSe…...

【Unity】UGUI的基本介绍
Unity的UGUI(Unity User Interface)是Unity引擎内自带的UI系统,官方称之为UnityUI,是目前Unity商业游戏开发中使用最广泛的UI系统开发解决方案。以下是关于Unity的UGUI的详细介绍: 一、UGUI的特点 灵活性:…...
MySQL 9.0新特性:向量存储
MySQL 9.0 正式版已经发布,其中一个亮点就是向量(VECTOR)数据类型的支持,本文给大家详细介绍一下这个新功能。 向量类型 MySQL 9.0 增加了一个新的向量数据类型:VECTOR。它是一种可以存储 N 个数据项的数据结构&…...
ruoyi实用性改造--(四)选择数据源及非标准使用数据库
一、实用型数据直接访问/** 使用Druid中 application-druid.yml 中定义的副数据源Connection con=null; //手工调用Druid的配置访问Connection con2=null;try {//DruidDataSource ds = SpringUtils.getBean("masterDataSource");DruidDataSource ds = Spring…...

HMI 的 UI 风格创造奇迹
HMI 的 UI 风格创造奇迹...

如何安全隐藏IP地址,防止网络攻击?
当您想在互联网上保持隐私或匿名时,您应该做的第一件事就是隐藏您的 IP 地址。您的 IP 地址很容易被追踪到您,并被用来了解您的位置。下面的文章将教您如何隐藏自己,不让任何试图跟踪您的活动的人发现。 什么是 IP 地址? 首先&am…...

Windows10/11家庭版开启Hyper-V虚拟机功能详解
Hyper-V是微软的一款虚拟机软件,可以使我们在一台Windows PC上,在虚拟环境下同时运行多个互相之间完全隔离的操作系统,这就实现了在Windows环境下运行Linux以及其他OS的可能性。和第三方虚拟机软件,如VMware等相比,Hyp…...

202487读书笔记|《我有个拥抱,你要不要》——生活从来如此,你的态度赋予它意义
202487读书笔记|《我有个拥抱,你要不要》——生活从来如此,你的态度赋予它意义 《我有个拥抱,你要不要》作者一天到晚气fufu,挺有愛的小漫画,适合用来看图说话锻炼小语言,我看的很快乐也写得很痛快…...

使用tcpdump抓取本本机的所有icmp包
1、抓取本机所有icmp包 tcpdump -i any icmp -vv 图中上半部分,是源主机tmp179无法ping通目标主机192.168.10.79(因为把该主机关机了)的状态,注意看,其中有unreachable 图中下半部分,是源主机tmp179可以p…...

Nginx:负载均衡小专题
运维专题 Nginx:负载均衡小专题 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/…...

新增多种图表类型,新增插件管理模块,DataEase开源数据可视化分析工具v2.8.0发布
2024年7月8日,人人可用的开源数据可视化分析工具DataEase正式发布v2.8.0版本。 这一版本的功能变动包括:图表方面,新增组合图、热力地图、符号地图、K线图等图表类型,并对已有的仪表盘、明细表、指标卡、富文本等图表类型进行了功…...

android perfetto使用技巧梳理
1 抓取方法 根据不同的配置参数,会显示不同的功能。 比如有的trace文件就无法显示线程状态信息,有的无法显示锁依赖信息等等,要看你的参数,我这个是很全的,基本够了,如果还想添加,可以命令行看…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...