一篇文章搞懂时间复杂度和空间复杂度

不知道小伙伴们有没有刷过力扣上的算法题,我在上研究生的时候,刷过了前40道题,上面的算法题,我觉得还挺难的,当你写完代码的时候,就可以提交自己写的代码到系统上,系统会给你写的代码计算时间复杂度和空间复杂度,并给出了你的排名。可能有的小伙伴不理解这个概念,今天我们来详细讲一下。

在编写和优化代码时,时间复杂度和空间复杂度是两个关键概念。它们帮助我们衡量算法的效率和资源使用情况,从而选择最优的解决方案。本文将详细探讨这两个概念,并通过具体的例子来说明它们在实际编程中的应用。

时间复杂度?

时间复杂度描述了一个算法的运行时间如何随着输入数据规模的增长而变化。它通常用大O符号表示,例如O(1)、O(n)、O(log n)等。以下是几种常见的时间复杂度类型及其含义:

O(1) - 常数时间复杂度
不管输入数据的大小如何,算法的执行时间始终相同。常数时间复杂度表示算法的运行时间不受输入数据规模的影响。

例子:

public int GetFirstElement(int[] array)
{return array[0];
}

解释:
这段代码总是返回数组的第一个元素,不管数组有多大,花费的时间都是一样的。这就像从一堆书里拿起最上面的一本书,不管书堆有多高,拿起一本书的时间始终不变。

示例图:

   函数调用:                    数组:GetFirstElement(array)        [10, 20, 30, 40, 50]|                       0   1   2   3   4|                           ↑返回 array[0]                ||O(1)  <--------------------+注释:访问数组第一个元素的操作始终是常数时间,不受数组大小影响。

通过这种方式,我们可以清晰地展示O(1)时间复杂度的概念,即无论输入数据的大小如何,算法的执行时间始终相同。

O(n) - 线性时间复杂度
算法的执行时间与输入数据规模成正比。当输入数据增大时,运行时间也线性增长。

**例子:**求数组每个元素之和

public int Sum(int[] array)
{int sum = 0;foreach (int item in array){sum += item;}return sum;
}

解释:
这个函数需要遍历整个数组来计算所有元素的总和。数组越大,需要的时间就越长。就像你需要逐个数数一堆硬币,硬币越多,数完的时间就越长。

示例图

scss复制代码函数调用:                       数组:
Sum(array)                       [10, 20, 30, 40, 50]|                           0   1   2   3   4|                           ↑   ↑   ↑   ↑   ↑
遍历每个元素  <------------------  ||
时间复杂度:O(n)  <---------------+注释:计算数组所有元素的总和需要遍历整个数组,运行时间与数组大小成正比。

O(log n) - 对数时间复杂度
算法的执行时间随着输入数据规模的增长按对数比例增加。这通常出现在需要将数据集分成较小部分的算法中,例如二分查找。

**例子:**在有序数组中查找目标元素的索引

public int BinarySearch(int[] array, int target)
{int left = 0;int right = array.Length - 1;while (left <= right){int mid = left + (right - left) / 2;if (array[mid] == target)return mid;if (array[mid] < target)left = mid + 1;elseright = mid - 1;}return -1;
}

解释:
这个函数使用二分查找法来寻找目标元素。每次迭代都会把搜索范围缩小一半。这就像在一本按字母顺序排列的字典里查一个词,每次翻开中间的页面,决定目标词在前半部分还是后半部分,然后重复这个过程。

示例图

scss复制代码函数调用:                       数组:
BinarySearch(array, target)     [10, 20, 30, 40, 50]|                          0   1   2   3   4|                         第一次比较:|                         mid = 2 -> 30 == target ?|                         目标小于30,搜索范围缩小一半|                         新范围: [10, 20]|                                  0   1|                         第二次比较:|                         mid = 0 -> 10 == target ?|                         目标大于10,搜索范围缩小一半|                         新范围: [20]|                                  1|                         第三次比较:|                         mid = 1 -> 20 == target ?|                         找到目标,返回索引1↑||O(log n) <----------------+注释:每次迭代搜索范围缩小一半,因此执行时间按对数比例增加。

O(n^2) - 平方时间复杂度
算法的执行时间与输入数据规模的平方成正比。这通常出现在嵌套循环中,每个循环遍历输入数据。

**例子:**将数组中的数据从小到大排序

public void BubbleSort(int[] array)
{for (int i = 0; i < array.Length - 1; i++){for (int j = 0; j < array.Length - i - 1; j++){if (array[j] > array[j + 1]){int temp = array[j];array[j] = array[j + 1];array[j + 1] = temp;}}}
}

解释:
这个函数使用冒泡排序算法对数组进行排序。它包含两个嵌套的循环,每个循环都会遍历数组。就像你要给一堆学生排座次,每次都要两两比较,整个过程需要很多次。

示例图

less复制代码函数调用:                        数组:
BubbleSort(array)                 [30, 10, 40, 20, 50]外层循环 i = 0:|                          第一次比较:30 > 10, 交换|                          新数组:[10, 30, 40, 20, 50]内层循环 j = 0:|                          第二次比较:30 > 40, 不交换|                          新数组:[10, 30, 40, 20, 50]|                          第三次比较:40 > 20, 交换|                          新数组:[10, 30, 20, 40, 50]|                          第四次比较:40 > 50, 不交换外层循环 i = 1:|                          第一次比较:10 > 30, 不交换|                          新数组:[10, 30, 20, 40, 50]内层循环 j = 1:|                          第二次比较:30 > 20, 交换|                          新数组:[10, 20, 30, 40, 50]|                          第三次比较:30 > 40, 不交换... (持续进行直到排序完成)↑||O(n^2) <---------------------+注释:每次外层循环遍历数组,内层循环也遍历数组,因此执行时间与数组大小的平方成正比。

O(2^n) - 指数时间复杂度
算法的执行时间随着输入数据规模的增长按指数比例增加。这种复杂度通常出现在递归算法中,尤其是解决组合问题时。

例子:

public int Fibonacci(int n)
{if (n <= 1)return n;return Fibonacci(n - 1) + Fibonacci(n - 2);
}

解释:
这个函数计算斐波那契数列的第n个数字。每次调用函数时,它会递归调用自身两次,导致总的调用次数按指数增长。

示例图

scss复制代码Fibonacci(5)|-------------|             |
Fib(4)        Fib(3)|             |
----         -----
|   |       |     |
Fib(3) Fib(2) Fib(2) Fib(1)|     |     |       |
---   ---   ---     ---
| |   | |   | |     |
Fib Fib Fib Fib Fib Fib
(2) (1) (1) (0) (1) (0)|...注释:每次调用函数时,它会递归调用自身两次,导致总的调用次数按指数增长,时间复杂度为 O(2^n)。
空间复杂度?

空间复杂度描述了一个算法在运行时需要的内存空间如何随着输入数据规模的增长而变化。以下是几种常见的空间复杂度类型及其含义:

O(1) - 常数空间复杂度
算法所需的内存空间不随输入数据规模的变化而变化。

例子:

public int GetFirstElement(int[] array)
{return array[0];
}

解释:
这个函数只返回数组的第一个元素,不需要额外的内存空间。就像你只拿一张桌子放书,无论书堆多高,只用一张桌子就够了。

示例图

scss复制代码函数调用:                      数组:
GetFirstElement(array)          [10, 20, 30, 40, 50]|                          0   1   2   3   4|                            ↑
返回 array[0]                        ||O(1)  <---------------------+注释:访问数组第一个元素的操作不需要额外的内存空间,内存使用量不随输入数据规模变化。

O(n) - 线性空间复杂度
算法所需的内存空间与输入数据规模成正比。

例子:

public int[] CopyArray(int[] array)
{int[] newArray = new int[array.Length];for (int i = 0; i < array.Length; i++){newArray[i] = array[i];}
}

解释:
这个函数创建了一个和输入数组一样大的新数组。就像你需要一个新的箱子来装一堆硬币,硬币越多,箱子就得越大。

示例图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

O(n^2) - 平方空间复杂度
算法所需的内存空间与输入数据规模的平方成正比。

例子:

public int[,] CreateMatrix(int n)
{int[,] matrix = new int[n, n];return matrix;
}

解释:
这个函数创建了一个n x n的矩阵。随着n的增加,所需的内存空间按平方增长。

示例图

scss复制代码函数调用:                        矩阵:
CreateMatrix(n)                   n = 2|                          [1, 1]|                          [1, 1]|                          矩阵大小:2 x 2||                          n = 3|                          [1, 1, 1]|                          [1, 1, 1]|                          [1, 1, 1]|                          矩阵大小:3 x 3||                          n = 4|                          [1, 1, 1, 1]|                          [1, 1, 1, 1]|                          [1, 1, 1, 1]|                          [1, 1, 1, 1]|                          矩阵大小:4 x 4↑||O(n^2)  <---------------------+注释:创建一个n x n的矩阵所需的内存空间随着n的平方增长。

O(2^n) - 指数空间复杂度
算法所需的内存空间随着输入数据规模的增长按指数比例增加。

**例子:**字符串的所有子集

public List<string> GenerateSubsets(string str)
{if (str.Length == 0){return new List<string> { "" };}char first = str[0];List<string> subsets = GenerateSubsets(str.Substring(1));List<string> newSubsets = new List<string>();foreach (string subset in subsets){newSubsets.Add(first + subset);newSubsets.Add(subset);}return newSubsets;
}

解释:
这个函数生成字符串的所有子集。随着字符串长度的增加,生成的子集数量按指数增长,需要的内存空间也按指数增长。

示例图

scss复制代码函数调用:
GenerateSubsets("abc")|---------------|             |
GenSub("bc")  GenSub("bc")|             |
GenSub("c")   GenSub("c")|             |
GenSub("")    GenSub("")|             |[""]           [""]生成的子集:["", "c", "b", "bc", "a", "ac", "ab", "abc"]空间复杂度:O(2^n)

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

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

相关文章

页面速度是如何影响SEO的?

搜索引擎使用复杂的算法来衡量您网站的重要方面&#xff0c;以决定是否向您发送流量。 搜索引擎使用您网站的小元素来确定您网站的质量和真实性&#xff0c;然后此操作将转化为您的网页在搜索引擎结果页面 中出现的位置。提高您在 SERP 中的排名的过程称为搜索引擎优化 (SEO)。…

第57期|GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

Datawhale - 角色要素提取竞赛

文章目录 赛题要求一、赛事背景二、赛事任务三、评审规则1.平台说明2.数据说明3.评估指标4.评测及排行 四、作品提交要求五、 运行BaselineStep1&#xff1a;下载相关库Step2&#xff1a;配置导入Step3&#xff1a;模型测试Step4&#xff1a;数据读取Step5&#xff1a;Prompt设…

Yi-1.5 9B Chat 上线Amazon SageMaker JumpStart

你是否对简单的API调用大模型感到不满足&#xff1f;是否因为无法亲自部署属于自己的大模型而烦恼&#xff1f; 好消息来了&#xff0c;Amazon SageMaker JumpStart 初体验 CloudLab实验上线啦&#xff01; 本实验将以零一万物最新发布的中文基础模型 Yi-1.5 9B Chat 为例&am…

kettle从入门到精通 第七十四课 ETL之kettle kettle调用https接口教程,忽略SSL校验

场景&#xff1a;kettle调用https接口&#xff0c;跳过校验SSL。&#xff08;有些公司内部系统之间的https的接口是没有SSL校验这一说&#xff0c;无需使用用证书的&#xff09; 解决方案&#xff1a;自定义插件或者自定义jar包通过javascript调用https接口。 1、http post 步…

嵌入式UI开发-lvgl+wsl2+vscode系列:8、控件(Widgets)(一)

一、前言 这里将介绍一系列控件&#xff0c;了解后就可以开始基础的开发了。 二、示例 1、Base Obj&#xff08;基础对象&#xff09; 1.1、示例1 #include "../../lv_examples.h" #if LV_BUILD_EXAMPLESvoid lv_example_obj_1(void) {lv_obj_t * obj1;obj1 lv…

Python容器 之 列表--列表的常用操作方法

1.查询相关方法&#xff1a;index()、count() &#xff08;1&#xff09;index() 说明&#xff1a; 和 字符串中的 find() 的作用是一样 列表中是没有 find() 方法的, 只有 index() 方法&#xff1b;字符串中 同时存在 find() 和 index() 方法 格式&#xff1a;列表.index(要查…

你必须要知道的自闭症知识,推荐收藏

自闭症&#xff0c;一种日益受到关注的神经发育障碍&#xff0c;对于许多人来说&#xff0c;仍充满了神秘和误解。以下是 12 个你必须知道的关于自闭症的重要知识点&#xff1a; 1、自闭症并非心理问题 自闭症是一种生理上的神经发育障碍&#xff0c;不是由于孩…

亚马逊TM商标跟卖,同行截流采集,人工手动跟卖选品更方便!

区分TM标&#xff0c;软件自动查询&#xff0c;人工手动查询方便。 大家好&#xff0c;跟大家说下如何区分TM标。 选择相对于的站点&#xff0c;选择TM。 软件采集出来的已备案、未备案TMR标&#xff0c;现在点击TM标就会跳到美国商标局。 可以清晰的看到这个地方只有一个序…

张颂文百花提名,男配界笑出“颂”彩

在这个星光熠熠的百花奖舞台上&#xff0c; 张颂文老师犹如一坛陈年老酒&#xff0c;越品越有味&#xff0c; 竟不声不响地提名了最佳男配角&#xff01;这下可好&#xff0c; 男配界仿佛一夜之间被“颂”风吹得花枝乱颤&#xff0c;笑料百出。你说张颂文老师这演技&#xf…

DreamTech联合南大和牛津发布最强3D内容生成大模型——Direct3D

文章链接&#xff1a;https://arxiv.org/pdf/2405.14832 github链接&#xff1a;https://nju-3dv.github.io/projects/Direct3D/ 从文本和图像生成高质量的3D资产一直是一项挑战&#xff0c;主要是由于缺乏能够捕捉复杂几何分布的可扩展3D表示。在这项工作中&#xff0c;介绍…

详解反向传播(BP)算法

文章目录 what&#xff08;是什么&#xff09;where&#xff08;用在哪&#xff09;How&#xff08;原理&&怎么用&#xff09;原理以及推导过程pytorch中的反向传播 what&#xff08;是什么&#xff09; 反向传播算法&#xff08;Backpropagation&#xff09;是一种用于…

自动驾驶水泥搅拌车在梁场的应用(下)

自动驾驶水泥搅拌车在梁场的应用&#xff08;下&#xff09; 北京渡众机器人科技有限公司的自动驾驶水泥搅拌车在梁场&#xff08;也称为预制梁场&#xff09;的应用可以带来多方面的优势和效益&#xff1a; 1. 自动化搅拌和运输 在梁场中&#xff0c;通常需要大量的混凝土搅…

自动化一些操作

下拉选择框 from selenium import webdriver from time import sleep # 导包 from selenium.webdriver.support.select import Select driver webdriver.Edge() driver.get(r"D:\WORK\ww\web自动化_day01_课件笔记资料代码\web自动化_day01_课件笔记资料代码\02_其他资料…

调试支付分回调下载平台证书

之前的原生代码放到webman里面&#xff0c;死活跑不通 没办法&#xff0c;只能用esayWeChat6.7 &#xff08;自行下载&#xff09; 它里面配置要用到平台证书 平台证书又要用到 composer require wechatpay/wechatpay 但是请求接口之前&#xff0c;你先要用到一个临时的平台…

配置atuin记录

https://atuin.sh/ 运行 curl --proto https --tlsv1.2 -LsSf https://setup.atuin.sh | sh报错 $ curl --proto https --tlsv1.2 -LsSf https://setup.atuin.sh | sh curl: (77) error setting certificate verify locations:CAfile: /etc/ssl/certs/ca-certificates.crtCAp…

同时安装JDK8和JDK17+环境变量默认无法修改

一、问题描述 当在windows系统中&#xff0c;同时安装JDK8和JDK17&#xff0c;环境变量默认就为jdk17&#xff0c;且从jdk17切换为jdk8后不生效&#xff0c;使用"java -version"命令查看后还是17版本。 解决方法 首先&#xff0c;产生的原因是&#xff0c;在安装…

2024最新源代码加密软件丨五款企业级软件评测

程序源代码作为企业的核心成果&#xff0c;一旦泄密将产生重大的损失&#xff0c;加密源代码至关重要。 可以防止他人未经授权使用、复制或修改源代码&#xff0c;保护开发者的劳动成果。 可以防止源代码被黑客或竞争对手获取和分析&#xff0c;减少漏洞被发现和利用的风险。…

JAVA极简图书管理系统,初识springboot后端项目

前提条件&#xff1a; 具备基础的springboot 知识 Java基础 废话不多说&#xff01; 创建项目 配置所需环境 将application.properties>application.yml 配置以下环境 数据库连接MySQL 自己创建的数据库名称为book_test server:port: 8080 spring:datasource:url:…

ShareSDK HarmonyOS NEXT集成指南

集成前准备 注册账号 使用MobSDK之前&#xff0c;需要先在MobTech官网注册开发者账号&#xff0c;并获取MobTech提供的AppKey和AppSecret&#xff0c;详情可以点击查看注册流程 ShareSDK流程图 集成配置 添加依赖 在Terminal窗口中&#xff0c;执行如下命令进行安装 ohpm …