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

【初阶数据结构篇】时间(空间)复杂度

文章目录

    • 算法
    • 复杂度
      • 时间复杂度
        • 1. 定义
        • 2. 表示方法
        • 3. 常见时间复杂度
        • 4.案例计算分析
            • 冒泡排序
            • 二分查找
            • 斐波那契数列(递归法)
            • 斐波那契数列(迭代法)
      • 空间复杂度
      • 案例分析
            • 冒泡排序
            • 斐波那契数列(递归法)
            • 斐波那契数列(迭代法)
      • 时间复杂度对比

正文

算法

算法(Algorithm):就是定义良好的计算过程,他取⼀个或⼀组的值为输⼊,并产⽣出⼀个或⼀组值作为输出。简单来说算法就是⼀系列的计算步骤,⽤来将输⼊数据转化成输出结果。

​ 程序=数据结构+算法,一个好的程序需要有一个好的算法,那如何去衡量一种算法的好坏呢?这就需要我们计算算法的复杂度。

复杂度

​ 复杂度是计算机科学中的一个基础概念,它帮助我们理解和评估算法的效率,对于算法设计和优化至关重要。算法的复杂度通常分为时间和空间复杂度两个方面。

时间复杂度


1. 定义

​ 在计算机科学中,算法的时间复杂度是⼀个函数式T(N),它定量描述了该算法的运⾏时间。时间复杂度是衡量程序的时间效率,那么为什么不去计算程序的运⾏时间呢?

​ 1.因为程序运⾏时间和编译环境和运⾏机器的配置都有关系,⽐如同⼀个算法程序,⽤⼀个⽼编译器进⾏编译和新编译器编译,在同样机器下运⾏时间不同。

​ 2.同⼀个算法程序,⽤⼀个⽼低配置机器和新⾼配置机器,运⾏时间也不同。

​ 3.并且时间只能程序写好后测试,不能写程序前通过理论思想计算评估。


2. 表示方法

​ 如定义所示,时间复杂度是一个函数式T(N),T(N)通过表示程序的指令的执行次数来定量描述程序的运行时间。

​ 例如,T(N)=10,T(N)=2N+10,T(N)=N2等等等,都是描述一个程序指令的执行次数

​ 但是,设想一下,采用这样的表示方法,如果两种算法一种T(N)=N2,另一种T(N)=N2+100,当N越大时二者差距就可以忽略不计,如果我们仍然这样表示,不免缺乏简洁性和统一性。

大O渐进表示法

​ 在这基础上,我们联想数学中所学的等阶无穷大概念,数学中使用小o来表示高阶无穷小,而采用大O来表示等阶无穷大。具体的来说,对于函数T(N),当N趋于无穷时,我们能否找到这样一个函数f(N),使得 T ( N ) f ( N ) \frac{T(N)}{f(N)} f(N)T(N)为一个常数,答案是可以的。


3. 常见时间复杂度

下面列出了一些常见时间复杂度O(N)的表示法,即f(N)的常见形式。

  • 常数时间复杂度:O(1),表示算法的执行时间不随输入规模的增长而变化,是最理想的情况。
  • 对数时间复杂度:O(log n),通常出现在二分查找等分治算法中。
  • 线性时间复杂度:O(n),表示算法的执行时间与输入规模成正比。
  • 线性对数时间复杂度:O(n log n),通常出现在快速排序、归并排序等分治算法中。
  • 平方时间复杂度:O(n2),通常出现在嵌套循环的算法中。
  • 指数时间复杂度:O(2n),通常出现在递归算法中。
  • 多项式时间复杂度:O(nk),k可能是大于 2 的正整数,这意味着算法在大规模数据上的性能下降较快。

4.案例计算分析
冒泡排序
// 计算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;}
}
  • 最好情况,若数组有序

​ T(N) =N

  • 最差情况,若数组与要求顺序反序

​ T(N) = N ∗ ( N − 1 ) 2 \frac{N*(N-1)}{2} 2N(N1)

有n个元素,需要排n-1趟,第i趟需要排n-i次

即(n-1)+(n-2)+……+1,结果如上所示

我们发现上述第一种是最好情况,而第二种是最坏情况,俗话说的好“做最好的准备,做最坏的打算”,所以很合理的我们应该将最坏的情况计算结果当做时间复杂度,上述即T[N]=N2


二分查找
// 计算BinarySearch的时间复杂度?
int BinarySearch(int* a, int n, int x)
{assert(a);int begin = 0;int end = n - 1;while (begin < end){int mid = begin + ((end - begin) >> 1);if (a[mid] < x)begin = mid + 1;else if (a[mid] > x)end = mid;elsereturn mid;}return -1;
}
  • 最好情况

    O(1)

  • 最坏情况

    O(logN)

    一次对半筛选,当数据很多时筛选k次才找到,2k=N,对数函数增长规律一样,为了保持统一性,下标可以忽略,建议写法即为logN。


斐波那契数列(递归法)
// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{if (N < 3)return 1;return Fib(N - 1) + Fib(N - 2);
}

在这里插入图片描述

以此类推,即为O(2N)。

斐波那契数列(迭代法)
long long  Fib(size_t n)
{int a = 1;int b = 1;int c = 1;while (n > 2){c = a + b;a = b;b = c;n--;}return c;
}
  • 可见我们使用迭代的方法,将时间复杂度降为了O(N)。

空间复杂度

类比时间复杂度,相似内容不再过多赘述了

  • 空间复杂度也是⼀个数学表达式,是对⼀个算法在运⾏过程中因为算法的需要额外临时开辟的空间。

  • 空间复杂度不是程序占⽤了多少bytes的空间,因为常规情况每个对象⼤⼩差异不会很⼤,所以空间复杂度算的是变量的个数。

  • 注意:函数运⾏时所需要的栈空间(存储参数、局部变量、⼀些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运⾏时候显式申请的额外空间来确定!


案例分析

下面我们用具体案例来熟悉空间复杂度的计算

冒泡排序
// 计算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;}
}
  • 我们只申请了常数个变量,所以很显然空间复杂度为O(1)

斐波那契数列(递归法)
// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{if (N < 3)return 1;return Fib(N - 1) + Fib(N - 2);
}
  • 空间复杂度为O(N)
  • 当我们输入N时,第一步递归将会沿着N-1,N-2一直到3递推,在n为3这个函数栈帧里调用2和1,并返回给3注意此时1和2的函数栈帧已经销毁,以此类推,返回一个销毁一个,程序在执行时同一时刻实际使用的空间不会超过n个(即往下递推的深度),只是每个n值相同函数栈帧在不同时刻执行了一次又一次的销毁创建过程,即在时间复杂度里面我们所讨论的调用次数的问题,但在空间复杂度中我们只关心使用的空间,故为O(N)。

斐波那契数列(迭代法)
long long  Fib(size_t n)
{int a = 1;int b = 1;int c = 1;while (n > 2){c = a + b;a = b;b = c;n--;}return c;
}
  • 这个也很显而易见了,为O(1)。

时间复杂度对比

下面是常见时间复杂度对比

在这里插入图片描述

在这里插入图片描述

相关文章:

【初阶数据结构篇】时间(空间)复杂度

文章目录 算法复杂度时间复杂度1. 定义2. 表示方法3. 常见时间复杂度4.案例计算分析冒泡排序二分查找斐波那契数列&#xff08;递归法&#xff09;斐波那契数列&#xff08;迭代法&#xff09; 空间复杂度案例分析冒泡排序斐波那契数列&#xff08;递归法&#xff09;斐波那契数…...

C# 设计模式分类

栏目总目录 1. 创建型模式&#xff08;Creational Patterns&#xff09; 创建型模式主要关注对象的创建过程&#xff0c;包括如何实例化对象&#xff0c;并隐藏实例化的细节。 单例模式&#xff08;Singleton&#xff09;&#xff1a;确保一个类只有一个实例&#xff0c;并提…...

前端模块化CommonJS、AMD、CMD、ES6

在前端开发中&#xff0c;模块化是一种重要的代码组织方式&#xff0c;它有助于将复杂的代码拆分成可管理的小块&#xff0c;提高代码的可维护性和可重用性。CommonJS、AMD&#xff08;异步模块定义&#xff09;和CMD&#xff08;通用模块定义&#xff09;是三种不同的模块规范…...

论文阅读:(DETR)End-to-End Object Detection with Transformers

论文阅读&#xff1a;&#xff08;DETR&#xff09;End-to-End Object Detection with Transformers 参考解读&#xff1a; 论文翻译&#xff1a;End-to-End Object Detection with Transformers&#xff08;DETR&#xff09;[已完结] - 怪盗kid的文章 - 知乎 指示函数&…...

react中路由跳转以及路由传参

一、路由跳转 1.安装插件 npm install react-router-dom 2.路由配置 路由配置&#xff1a;react中简单的配置路由-CSDN博客 3.实现代码 // src/page/index/index.js// 引入 import { Link, useNavigate } from "react-router-dom";function IndexPage() {const …...

C++ STL set_symmetric_difference

一&#xff1a;功能 给定两个集合A&#xff0c;B&#xff1b;求出两个集合的对称差&#xff08;只属于其中一个集合&#xff0c;而不属于另一个集合的元素&#xff09;&#xff0c;即去除那些同时在A&#xff0c;B中出现的元素。 二&#xff1a;用法 #include <vector>…...

postman请求响应加解密

部分接口&#xff0c;需要请求加密后&#xff0c;在发动到后端。同时后端返回的响应内容&#xff0c;也是经过了加密。此时&#xff0c;我们先和开发获取到对应的【密钥】&#xff0c;然后在postman的预执行、后执行加入js脚本对明文请求进行加密&#xff0c;然后在发送请求&am…...

数据集,批量更新分类数值OR批量删除分类行数据

数据集批量更新分类OR删除分类行数据 import osdef remove_class_from_file(file_path, class_to_remove):"""从YOLO格式的标注文件中删除指定类别的行记录&#xff0c;并去除空行。:param file_path: YOLO标注文件路径:param class_to_remove: 需要删除的类别…...

一款功能强大的视频编辑软件会声会影2023

会声会影2023是一款功能强大的视频编辑软件&#xff0c;由加拿大Corel公司制作&#xff0c;正版英文名称为‌Corel VideoStudio。它具备图像抓取和编修功能&#xff0c;可以处理和转换多种视频格式&#xff0c;如‌MV、‌DV、‌V8、‌TV和实时记录抓取画面文件。会声会影提供了…...

政安晨【零基础玩转各类开源AI项目】基于Ubuntu系统部署LivePortrait :通过缝合和重定向控制实现高效的肖像动画制作

目录 项目论文介绍 论文中实际开展的工作 非扩散性的肖像动画 基于扩散的肖像动画 方法论 基于Ubuntu的部署实践开始 1. 克隆代码并准备环境 2. 下载预训练权重 3. 推理 快速上手 驱动视频自动裁剪 运动模板制作 4. Gradio 界面 5. 推理速度评估 社区资源 政安…...

在Spring项目中使用Maven和BCrypt来实现修改密码功能

简介 在数字时代&#xff0c;信息安全的重要性不言而喻&#xff0c;尤其当涉及到个人隐私和账户安全时。每天&#xff0c;无数的用户登录各种在线服务&#xff0c;从社交媒体到银行账户&#xff0c;再到电子邮件和云存储服务。这些服务的背后&#xff0c;是复杂的系统架构&am…...

RedHat8安装Oracle19C

RedHat8安装Oracle19C 1、 更新yum源 更新yum源为阿里云镜像源&#xff1a; # 进入源目录 cd /etc/yum.repos.d/ # 删除 redhat 默认源 rm redhat.repo # 下载阿里云的centos7源 curl -O http://mirrors.aliyun.com/repo/Centos-8.repo # 替换 Centos-8.repo 中的 $releasev…...

React系列面试题

大家好&#xff0c;我是有用就点赞&#xff0c;有用就扩散。 1.React的组件间通信都有哪些形式&#xff1f; 父传子&#xff1a;在React中&#xff0c;父组件调用子组件时可以将要传递给子组件的数据添加在子组件的属性中&#xff0c;在子组件中通过props属性进行接收。这个就…...

C#:通用方法总结—第6集

大家好&#xff0c;今天继续介绍我们的通用方法系列。 下面是今天要介绍的通用方法&#xff1a; &#xff08;1&#xff09;这个通用方法为SW查找草图数量 /// <summary> /// 查找草图数量 /// </summary> /// <param name"doc2"></param>…...

Spark实时(一):StructuredStreaming 介绍

文章目录 Structured Streaming 介绍 一、SparkStreaming实时数据处理痛点 1、复杂的编程模式 2、SparkStreaming处理实时数据只支持Processing Time 3、微批处理,延迟高 4、精准消费一次问题 二、StructuredStreaming架构与场景应用 三、​​​​​​​​​​​​​​…...

LangChain4j-RAG基础

RAG是什么 简而言之&#xff0c;RAG 是一种在将数据发送到 LLM 之前从数据中查找相关信息并将其注入到提示中的方法。这样LLM将获得&#xff08;希望&#xff09;相关信息&#xff0c;并能够使用这些信息进行回复&#xff0c;这应该会减少产生幻觉的可能性。 实现方法: 全文…...

git--本地仓库修改同步到远程仓库

尝试将本地分支推送到远程仓库时&#xff0c;出现一个非快速前进的错误。通常是因为远程仓库中的分支包含本地分支没有的提交。在推送之前&#xff0c;需要将远程仓库的更改合并到本地分支。 解决步骤如下&#xff1a; 切换到你的本地分支&#xff1a; 确保处于想要推送的分支…...

剑和沙盒 3 - 深度使用和解析Windows Sandbox

介绍 两年前&#xff0c;微软作为Insiders build 18305的一部分发布了一项新功能- Windows Sandbox。 该沙箱具有一些有用的规格&#xff1a; Windows 10&#xff08;Pro/Enterprise&#xff09;的集成部分。在 Hyper-V 虚拟化上运行。原始且可抛弃 – 每次运行时都干净地开…...

深度学习loss

pytorch模型训练demo代码 在PyTorch中&#xff0c;模型训练通常涉及几个关键步骤&#xff1a;定义模型、定义损失函数、选择优化器、准备数据加载器、编写训练循环。以下是一个简单的PyTorch模型训练演示代码&#xff0c;该代码实现了一个用于手写数字识别&#xff08;使用MNIS…...

编写一个Chrome插件,网页选择文字后,右键出现菜单“search with bing”,选择菜单后用bing搜索文字

kimi ai 生成&#xff0c;测试可用&#xff0c;需要自行准备图标文件 创建一个简单的Chrome插件来实现选择文本后的搜索功能&#xff0c;你需要完成以下几个步骤&#xff1a; 创建插件的基础文件夹和文件&#xff1a; 创建一个文件夹用于存放插件的所有文件。在该文件夹中创建以…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; 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…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...