算法时间复杂度

article/2025/11/11 7:12:28

在 算法基础 中,我们简单介绍了什么是算法、对算法的要求,以及说了评断算法效率的两大类方法。今天我们将重点介绍衡量算法效率的一个概念——时间复杂度。


定义

在进行算法分析的时候,语句的总执行次数 T(n) 是关于问题规模 n(输入数据量)的函数,换句话说:代码总的执行时间 T(n) 和每行代码执行的次数 n 成正比。一般记做 T(n)=O(f(n))。其中用大写 O() 来体现时间复杂度的记法,我们称之为大 O 记法。

大 O 时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以,也叫作渐进时间复杂度(asymptotic time complexity),简称时间复杂度。

那什么情况下,算法的时间复杂度才好呢?当然是「多个算法中,随着 n 的增大,T(n) 增长最慢」的算法才是好算法呀。

既然说到了「慢」,怎样就增长得慢了呢?想想咱们说一个人跑得快,是不是就是说他跑的速率低呀,那类比过来,无疑是增长率(增量/原总量*100%)比较低的增长得慢了呗。

大 O 记法

常见时间复杂度

常见时间复杂度
常用的时间复杂度所耗费的时间从少到多依次是:
在这里插入图片描述
再贴一个盗来的图吧:
在这里插入图片描述

大 O 阶方法的推导

  1. 用常数 1 取代运行时间中的所有加法常数。
  2. 在修改后的运行次数函数中,只保留最高阶项。
  3. 如果最高阶项存在且不是1,则去除与这个项相乘的常数。

得到的结果就是大O阶。

常见时间复杂度实例分析

推导时间复杂度的时候,上述的「大 O 阶方法的推导」一定要用上,再分享下自己常用的几个法则:

  • 法则一:只关注循环执行次数最多的一段代码
  • 法则二:加法法则->总复杂度等于量级最大的那段代码的复杂度
  • 法则三:乘法法则->嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

常数阶

与问题的大小(n 的大小)无关,执行时间恒定的算法,称之为具有 O(1) 的时间复杂度,又叫常数阶。

不管常数是多少,都记作 O(1) ,而不是 O(2)O(4) 等其它数字。

另外,对于单纯的分支结构(不在循环内)来说,不管真假执行的次数都是恒定的,不会随 n 的大小变化。

线性阶

比如看下面的代码:

int i;
for (i = 0; i < n; i++){    // 时间复杂度为 O(1) 的程序步骤序列
}

循环结构的代码比单纯的分支结构代码或者只执行固定次数的代码复杂一些。咱们要确定时间复杂度的话,需要确定某个语句(集)执行的次数。

这个时候法则一和三就登场了:最外层循环执行 n 次,循环体中的执行都是 1 次,n*1=n,显而易见上述代码的时间复杂度为 O(n)

对数阶

看下面代码:

int count = 1;
while (count < n){// 时间复杂度为 O(1) 的程序步骤序列count = count * 2;
}

根据法则一,咱们只关注循环执行次数最多的一段代码,这个循环执行多少次呢?是不是会有这个式子 2 x 2^x 2x=n,算出来 x 是不是 x= log ⁡ 2 n \log_2n log2n;然后再利用法则三,是不是可以算出来上述代码的时间复杂度为 log ⁡ 2 n \log_2n log2n 了。

如果代码中的 count = count * 2;count = count * 3; 呢,是不是就不用说了。

平方阶

下面的代码是个双层 for 循环:

int i, j;
for (i = 0; i < n; i++){    for (j = 0; j < n; j++){        // 时间复杂度为 O(1) 的程序步骤序列 }
}

内循环的时间复杂度是 O(n),咱们已经分析过了。外层的循环次数也是 n 次,法则三直接可以得出上述代码的时间复杂度为 O( n 2 n^2 n2)。

如果上述代码是下面的样子呢:

int i, j;
for (i = 0; i < m; i++){    for (j = 0; j < n; j++){        // 时间复杂度为 O(1) 的程序步骤序列 }
}

没错,就是 O( m n mn mn)。

再来个有难度的例子:

int i, j;
for (i = 0; i < n; i++){   // 注意现在是 j=i,而不是 j=0for (j = i; j < n; j++){        // 时间复杂度为 O(1) 的程序步骤序列    }
}

上述代码的时间复杂度是多少呢?简单分析下:

  • 当 i=0 时,内循环执行 n 次;
  • 当 i=1 时,内循环执行了 n-1 次;
  • ……;
  • 当 i=n-1 时,执行 1 次;
  • 总的执行次数为 n + ( n − 1 ) + ( n − 2 ) + … + 1 n+(n-1)+(n-2)+…+1 n+(n1)+(n2)++1 = = = n ( n + 1 ) 2 \frac {n(n+1)}{2}\quad 2n(n+1) = = = n 2 2 \frac{n^2}{2} 2n2+ n 2 \frac n2 2n

此时,就到大 O 阶方法的推导发挥的时候了:

  1. 第一条,没有加法常数,不考虑;
  2. 第二条,保留最高项,得到 n 2 2 \frac {n^2} 2 2n2
  3. 第三条去除最高项的常数,也就是 1 2 \frac 12 21,得到时间复杂度为 O( n 2 n^2 n2)。

其他名词

先来一段代码吧:

// n 表示数组 array 的长度
int find(int[] array, int n, int x) {int i = 0;int position = -1;for (; i < n; ++i) {if (array[i] == x){position = i;}}return position;
}

上述代码的功能是在一个无序数组中,查找变量 x 出现的位置,如果没找到,则返回 -1。由上面说到的分析方法,不难知道代码的时间复杂度为 O( n n n)。

下面我们来做下优化,如果我们在数组中查找某个元素,是并不需要把数组中的所有元素遍历一遍的,因为中途可能就发现答案,然后就可以提前结束循环了。下面的代码是优化过的,这个时候时间复杂度就不为 O( n n n) 了。

// n 表示数组 array 的长度
int find(int[] array, int n, int x) {int i = 0;int position = -1;for (; i < n; ++i) {if (array[i] == x){position= i;break;}}return position;
}

针对上述代码,咱们分三种情况讨论:

  • 情况一:数组中的第一个元素就是待查找元素,时间复杂度为 O( 1 1 1);
  • 情况二:数组中的最后一个元素是待查找元素,时间复杂度为 O( n n n);
  • 情况三:在数组中的不确定的位置,位置有 n+1 种情况(在数组中,不在数组中),我们把每种情况下的需要遍历的元素个数加起来,然后除 n+1,得到需要遍历元素的评价值:即 1 + 2 + 3 + … … + n + n n + 1 \frac {1+2+3+……+n+n}{n+1} n+11+2+3++n+n= n ( n + 3 ) 2 ( n + 1 ) \frac {n(n+3)}{2(n+1)} 2(n+1)n(n+3),然后再根据上文说到的计算时间复杂度的规则,得到平均时间复杂度为 O( n n n)。

情况三中涉及到概率问题,具体的看图吧(重点已经标注):在这里插入图片描述

这次再引入下面三个名词应该就好点了吧:

  1. 最好情况时间复杂度:在最理想的情况下,执行这段代码的时间复杂度。

  2. 最坏情况时间复杂度:在最糟糕的情况下,执行这段代码的时间复杂度。

  3. 平均情况时间复杂度:看图上的说明即可~

均摊时间复杂度,还是看下极客时间的教程吧:
在这里插入图片描述
其实大概意思就是如果对某个数据结构进行一组连续操作的时候,大部分情况下时间复杂度还是很低的,个别比较高,这个时候咱们将这一组操作放一块看,把时间复杂度较高的操作耗时平摊到耗时低的操作上。而且 在能够应用均摊时间复杂度分析的场合,一般均摊时间复杂度就等于最好情况时间复杂度。

这部分内容的话,推荐大家看看 复杂度分析(下):浅析最好、最坏、平均、均摊时间复杂度。


这篇博客虽然不是特别长,但是写出来耗费的时间还挺长;虽也没有生动的例子,还是希望自己一个各位能好好理解并应用了;虽然只是简单介绍了时间复杂度的相关内容,但是还可以看看下篇的 空间复杂度 啊~


http://chatgpt.dhexx.cn/article/LoVXGq9o.shtml

相关文章

java时间复杂度计算_时间复杂度到底怎么算

算法(Algorithm)是指用来操作数据、解决程序问题的一组方法。对于同一个问题&#xff0c;使用不同的算法&#xff0c;也许最终得到的结果是一样的&#xff0c;但在过程中消耗的资源和时间却会有很大的区别。 那么我们应该如何去衡量不同算法之间的优劣呢&#xff1f; 主要还是从…

Python 时间复杂度计算

一、时间复杂度 1 常见的时间复杂度 #常量阶O(1)# 对数阶O(logn)# 线性对数阶O(nlogn)# 线性阶O(n)# 平方阶,立方阶....M次方阶O(n^2),O(n^3),O(n^m)# 指数阶O(2^n)# 阶乘阶O(n!) 算法的时间复杂度对比&#xff1a; O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2lo…

树的时间复杂度

时间复杂度是一个函数&#xff0c;它定量描述了该算法的运行时间。常见的时间复杂度有以下几种。 1&#xff0c;log(2)n&#xff0c;n&#xff0c;n log(2)n &#xff0c;n的平方&#xff0c;n的三次方&#xff0c;2的n次方&#xff0c;n! 1指的是常数。即&#xff0c;无论算法…

时间复杂度和空间复杂度详解

算法时间复杂度和空间复杂度 1.算法效率 算法效率分析分为两种&#xff1a;第一种是时间效率&#xff0c;第二种是空间效率。时间效率被称为时间复杂度&#xff0c;而空间效率被称作空间复杂度。 时间复杂度主要衡量的是一个算法的运行速度&#xff0c;而空间复杂度主要衡量一…

全排列的时间复杂度

我们在高中的时候都学过排列组合。“如何把 n 个数据的所有排列都找出来”&#xff0c;这就是全排列的问题。我来举个例子。比如&#xff0c;1&#xff0c;2&#xff0c;3 这样 3 个数据&#xff0c;有下面这几种不同的排列&#xff1a; 1, 2, 3 1, 3, 2 2, 1, 3 2, 3, 1 3, 1…

十分钟搞定时间复杂度(算法的时间复杂度)

目录 1、什么是时间复杂度&#xff1f; 2、时间复杂度的计算 &#xff08;1&#xff09;单个循环体的推导法则 &#xff08;2&#xff09;多重循环体的推导法则 &#xff08;3&#xff09;多个时间复杂度的推导法则 &#xff08;4&#xff09;条件语句的推导法则 3、习题…

时间复杂度

时间频率 一个算法执行所耗费的时间&#xff0c;从理论上是不能算出来的&#xff0c;必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试&#xff0c;只需知道哪个算法花费的时间多&#xff0c;哪个算法花费的时间少就可以了。并且一个算法花费的时间与算…

什么是时间复杂度?

时间复杂度&#xff08;Time complexity&#xff09;是一个函数&#xff0c;它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数. 时间复杂度常用大O表述&#xff0c;不包括这个函数的低阶项和首项系数。 常见的时间复杂度 常见的算法时间复杂度由小到大…

数据结构—1.时间复杂度

目录 前言 一、时间复杂度 二、大O表示法 三&#xff0c;实例介绍 例1&#xff1a;O(N^2) 例2&#xff1a;O&#xff08;1&#xff09; 例3&#xff1a;O(M N) &#xff08;重点&#xff09;例4&#xff1a;O&#xff08;N&#xff09; 例5&#xff1a;冒泡排序&#…

时间复杂度计算-例题集合

一、常数阶二、线性阶三、对数阶四、平方阶五、多个复杂度组合&#xff1a;顺序结构六、多个复杂度组合&#xff1a;选择结构七、多个复杂结构&#xff1a;嵌套结构八、递归 ) 一、常数阶 // 常数阶 int result 100; //运行程序只执行一次 result ; //执行一次System.out…

时间复杂度详解

目录 一. 时间复杂度概念 例题1: 二. 推导大O阶 三. 几种常见的时间复杂度: 3.1常数阶: 3.2线性阶: 例题2: 3.3对数阶 3.4 平方阶: ​编辑 例题3:​编辑 解题思路: 变式1: 3.5 总结 四、空间复杂度 4.1 空间复杂度O(1) 4.2空间复杂度O(n) 例题4&#xff1a;数字…

一套图 搞懂“时间复杂度”

写在前面&#xff1a; 这篇文章是在公众号&#xff1a; 程序员小灰 中发布的。是我到目前为止所看到的关于时间复杂度介绍的最好的文章&#xff0c;清晰明了。 所以拿来po出来 仅供学习交流&#xff0c;如侵则删。 现已将此文收录至&#xff1a; 《数据结构》C语言版 (清华严…

各位学弟学妹,别再看教材了,时间复杂度看这篇就好了

时间复杂度是学习算法的基石&#xff0c;今天我们来聊聊为什么要引入时间复杂度&#xff0c;什么是时间复杂度以及如何去算一个算法的时间复杂度 一、刻画算法的运行时间 某日&#xff0c;慧能叫来了一尘打算给他补习补习一下基础知识&#xff0c;只见克写了一段非常简单的代码…

pytorch—torch.tensor.scatter操作解析

torch.Tensor.scatter_(dim, index, src, reduceNone) 理解scatter操作: tensor_A.scatter_(dim, index, tensor_B): tensor_B的每个元素&#xff0c;都按照 index 被scatter&#xff08;可以理解为填充&#xff09;到目标tensor_A中。 (1) index和源tensor_B维度一致; (2) t…

python scatter参数详解_python matplotlib.scatter 用法

# -*- coding: utf-8 -*- #导入模块 from matplotlib import pyplot as plt import numpy as np import pprint from math import pi,sin A1np.array([0,0]) B1np.array(([2,0],[0,2])) #以 A1为均值&#xff0c;B1为协方差矩阵&#xff0c;生成正态分布的随机数 每次生…

pytorch scatter和scatter_详解

文章目录 0. Introduction1. 定义2. 详解例1例2 Reference&#xff1a; 0. Introduction scatter() 和 scatter_() 的作用是一样的&#xff0c;只不过 scatter() 不会直接修改原来的 Tensor&#xff0c;而 scatter_() 会 PyTorch 中&#xff0c;一般函数加下划线代表直接在原来…

Pytorch中scatter与gather操作

文章目录 数据发散scatter带聚集的发散scatter_add_onnx中scatterND数据聚集gather 数据发散scatter 函数原型pytorch官方文档scatter_&#xff1a; scatter_(dim, index, src) → Tensor注&#xff1a; scatter_是scatter的就地操作。 对于一个三维的张量来说&#xff0c;张…

pytorch中scatter()、scatter_()详解

scatter()、scatter_() scatter() 和 scatter_() 的作用一样。 不同之处在于 scatter() 不会直接修改原来的 Tensor&#xff0c;而 scatter_() 会在原来的基础上对Tensor进行修改。 torch.scatter()官方文档 scatter(dim, index, src)将src中数据根据index中的索引按照dim的…

torch_scatter.scatter()的使用方法详解

目录 1. 参数2. 示例2.1 简单示例2.2 顺序问题2.3 维度问题 1. 参数 具体来讲&#xff0c;scatter函数的作用就是将index中相同索引对应位置的src元素进行某种方式的操作&#xff0c;例如sum、mean等&#xff0c;然后将这些操作结果按照索引顺序进行拼接。下面我用具体的例子来…

torch.scatter

本文目录 一、函数简介二、二维举例三、详解执行过程1. 第一步2. 第二步3. 第三步4. 问题 一、函数简介 torch.scatter(input, dim, index, src) dim ([int]) – the axis along which to indexindex (LongTensor) – the indices of elements to scatter, can be either emp…