什么是时间复杂度?

article/2025/11/10 18:59:15

  时间复杂度(Time complexity)是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数. 时间复杂度常用大O表述,不包括这个函数的低阶项和首项系数。

  常见的时间复杂度

  

常见的算法时间复杂度由小到大依次为

.  

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

时间复杂度的意义

究竟什么是时间复杂度呢?让我们来想象一个场景:

某一天,小灰和大黄同时加入了一个公司......

640?wx_fmt=jpeg

一天过后,小灰和大黄各自交付了代码,两端代码实现的功能都差不多。

大黄的代码运行一次要花100毫秒,内存占用5MB。

小灰的代码运行一次要花100秒,内存占用500MB。

于是......

640?wx_fmt=jpeg

640?wx_fmt=jpeg

由此可见,衡量代码的好坏包括两个非常重要的指标:

1.运行时间

2.占用空间

640?wx_fmt=jpeg

640?wx_fmt=jpeg

基本操作执行次数

关于代码的基本操作执行次数,我们用四个生活中的场景来做一下比喻:

场景1. 给小灰一条长10寸的面包,小灰每3天吃掉1寸,那么吃掉整个面包需要几天?

640?wx_fmt=jpeg

答案自然是 3 X 10 = 30天。

如果面包的长度是 N 寸呢?

此时吃掉整个面包,需要 3 X n = 3n 天。

如果用一个函数来表达这个相对时间,可以记作 T(n) = 3n。

场景2.  给小灰一条长16寸的面包,小灰每5天吃掉面包剩余长度的一半,第一次吃掉8寸,第二次吃掉4寸,第三次吃掉2寸......那么小灰把面包吃得只剩下1寸,需要多少天呢?

这个问题翻译一下,就是数字16不断地除以2,除几次以后的结果等于1?这里要涉及到数学当中的对数,以2位底,16的对数,可以简写为log16。

因此,把面包吃得只剩下1寸,需要 5 X log16 = 5 X 4 = 20 天。

如果面包的长度是 N 寸呢?

需要 5 X logn = 5logn天,记作 T(n) = 5logn。

场景3.  给小灰一条长10寸的面包和一个鸡腿,小灰每2天吃掉一个鸡腿。那么小灰吃掉整个鸡腿需要多少天呢?

640?wx_fmt=jpeg

答案自然是2天。因为只说是吃掉鸡腿,和10寸的面包没有关系 。

如果面包的长度是 N 寸呢?

无论面包有多长,吃掉鸡腿的时间仍然是2天,记作 T(n) = 2。

场景4.  给小灰一条长10寸的面包,小灰吃掉第一个一寸需要1天时间,吃掉第二个一寸需要2天时间,吃掉第三个一寸需要3天时间.....每多吃一寸,所花的时间也多一天。那么小灰吃掉整个面包需要多少天呢?

答案是从1累加到10的总和,也就是55天。

如果面包的长度是 N 寸呢?

此时吃掉整个面包,需要 1+2+3+......+ n-1 + n = (1+n)*n/2 = 0.5n^2 + 0.5n。

记作 T(n) = 0.5n^2 + 0.5n。

640?wx_fmt=jpeg

上面所讲的是吃东西所花费的相对时间,这一思想同样适用于对程序基本操作执行次数的统计。刚才的四个场景,分别对应了程序中最常见的四种执行方式:

场景1, T(n) = 3n,执行次数是线性的。

 
  1. void eat1(int n){

  2.    for(int i=0; i<n; i++){;

  3.        System.out.println("等待一天");

  4.        System.out.println("等待一天");

  5.        System.out.println("吃一寸面包");

  6.    }

  7. }

vo

场景2, T(n) = 5logn,执行次数是对数的。

 
  1.  

  2. void eat2(int n){

  3.    for(int i=1; i<n; i*=2){

  4.        System.out.println("等待一天");

  5.        System.out.println("等待一天");

  6.        System.out.println("等待一天");

  7.        System.out.println("等待一天");

  8.        System.out.println("吃一半面包");

  9.    }

  10. }

  11.  

场景3,T(n) = 2,执行次数是常量的。

 
  1.  

  2. void eat3(int n){

  3.    System.out.println("等待一天");

  4.    System.out.println("吃一个鸡腿");

  5. }

  6.  

场景4,T(n) = 0.5n^2 + 0.5n,执行次数是一个多项式。

 
  1.  

  2. void eat4(int n){

  3.    for(int i=0; i<n; i++){

  4.        for(int j=0; j<i; j++){

  5.            System.out.println("等待一天");

  6.        }

  7.        System.out.println("吃一寸面包");

  8.    }

  9. }

渐进时间复杂度

有了基本操作执行次数的函数 T(n),是否就可以分析和比较一段代码的运行时间了呢?还是有一定的困难。

比如算法A的相对时间是T(n)= 100n,算法B的相对时间是T(n)= 5n^2,这两个到底谁的运行时间更长一些?这就要看n的取值了。

所以,这时候有了渐进时间复杂度(asymptotic time complectiy)的概念,官方的定义如下:

若存在函数 f(n),使得当n趋近于无穷大时,T(n)/ f(n)的极限值为不等于零的常数,则称 f(n)是T(n)的同数量级函数。

记作 T(n)= O(f(n)),称O(f(n))为算法的渐进时间复杂度,简称时间复杂度。

渐进时间复杂度用大写O来表示,所以也被称为大O表示法。

640?wx_fmt=jpeg

640?wx_fmt=jpeg

如何推导出时间复杂度呢?有如下几个原则:

  1. 如果运行时间是常数量级,用常数1表示。

  2. 只保留时间函数中的最高阶项

  3. 如果最高阶项存在,则省去最高阶项前面的系数。

让我们回头看看刚才的四个场景。

场景1:

T(n) = 3n 

最高阶项为3n,省去系数3,转化的时间复杂度为:

T(n) =  O(n)

640?wx_fmt=png

场景2:

T(n) = 5logn 

最高阶项为5logn,省去系数5,转化的时间复杂度为:

T(n) =  O(logn)

640?wx_fmt=png

场景3:

T(n) = 2

只有常数量级,转化的时间复杂度为:

T(n) =  O(1)

640?wx_fmt=png

场景4:

T(n) = 0.5n^2 + 0.5n

最高阶项为0.5n^2,省去系数0.5,转化的时间复杂度为:

T(n) =  O(n^2)

640?wx_fmt=png

这四种时间复杂度究竟谁用时更长,谁节省时间呢?稍微思考一下就可以得出结论:

O(1)< O(logn)< O(n)< O(n^2)

在编程的世界中有着各种各样的算法,除了上述的四个场景,还有许多不同形式的时间复杂度,比如:

O(nlogn), O(n^3), O(m*n),O(2^n),O(n!)

今后遨游在代码的海洋里,我们会陆续遇到上述时间复杂度的算法。

640?wx_fmt=png

时间复杂度的巨大差异

640?wx_fmt=jpeg

640?wx_fmt=jpeg

我们来举过一个栗子:

算法A的相对时间规模是T(n)= 100n,时间复杂度是O(n)

算法B的相对时间规模是T(n)= 5n^2,时间复杂度是O(n^2),

算法A运行在小灰家里的老旧电脑上,算法B运行在某台超级计算机上,运行速度是老旧电脑的100倍。

那么,随着输入规模 n 的增长,两种算法谁运行更快呢?

640?wx_fmt=png

从表格中可以看出,当n的值很小的时候,算法A的运行用时要远大于算法B;当n的值达到1000左右,算法A和算法B的运行时间已经接近;当n的值越来越大,达到十万、百万时,算法A的优势开始显现,算法B则越来越慢,差距越来越明显。

这就是不同时间复杂度带来的差距。

640?wx_fmt=jpeg


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

相关文章

数据结构—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…

Python中的scatter

假设X与Y&#xff0c;其中X是5X2矩阵 关于X_demo[Y_demo0 , 0],是一种获取子矩阵的方式 因为Y_demo取值只是0与1&#xff0c;可以看做一个布尔数组&#xff0c; 在X_demo[取Y_demo中为0的行&#xff0c;只取第0列] 正好对应 而在scatter(横坐标&#xff0c;纵坐标) 现在已经…

scatter python_Python中scatter()函数--转载

原博文 2017-05-13 20:46 − 原博地址:http://blog.csdn.net/anneqiqi/article/details/64125186 最近开始学习Python编程,遇到scatter函数,感觉里面的参数不知道什么意思于是查资料,最后总结如下: 1、scatter函数原型 2、其中散点的形状参数marker如下:... 相关推荐 …

scatter python_python中的scatter()方法

1、scatter函数原型 2、其中散点的形状参数marker如下&#xff1a; 3、其中颜色参数c如下: 4、基本的使用方法如下&#xff1a; #导入必要的模块 importnumpy as np importmatplotlib.pyplot as plt #产生测试数据 x np.arange(1,10) y x fig plt.figure() ax1 fig.a…

scatter python_Python的散点图绘制 scatter

python能画的图种类非常多&#xff0c;而且看上去都很好看&#xff0c;具体种类部分可参看&#xff1a;https://matplotlib.org/api/_as_gen/matplotlib.pyplot.figure.html#matplotlib.pyplot.figure 这里主要是探索下散点图绘制。 1. 首先是导入包&#xff0c;创建数据 imp…

scatter python_Python scatter详解

函数原型:matplotlib.pyplot.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None,vmin=None, vmax=None, alpha=None, linewidths=None,verts=None, edgecolors=None, hold=None, data=None,**kwargs) 参数作用如下: x, y位置。 s大小。 c颜色,可能的情况…

scatter

scatter 散点图 全页折叠 语法 scatter(x,y) scatter(x,y,sz) scatter(x,y,sz,c) scatter(___,filled) scatter(___,mkr) scatter(___,Name,Value) scatter(ax,___) s scatter(___) 说明 示例 scatter(x,y) 在向量 x 和 y 指定的位置创建一个包含圆形的散点图。该类型的图形也…

py使用scatter画散点/气泡图

本博文源于《python数据可视化》&#xff08;黑马程序员编著&#xff09;。旨在讲解python如何使用scatter函数进行绘画散点图和气泡图。先讲解scatter函数参数如何使用&#xff0c;然后再演示两个例子进行绘画散点图和气泡图 scatter函数参数讲解 scatter(x,y,sNone,cNone,m…

ComposeOptions.kotlinCompilerVersion is deprecated

我为我的 Compose 工程升级 AGP 后 &#xff08;7.0.0 > 7.0.2&#xff09;重新编译发生下面错误 ComposeOptions.kotlinCompilerVersion is deprecated. Compose now uses the kotlin compiler defined in your buildscript. 以前需要通过该 composeOptions 指定 Kotlin 版…