全文目录

  • 引言
    • 如何衡量一个算法的好坏
  • 时间复杂度
    • 时间复杂度的定义
    • 时间复杂度的大O表示法
  • 实例
    • test1
    • test2
    • test3
    • test4
    • test5
  • 总结

引言

如何衡量一个算法的好坏

我们在写算法的时候,对于实现同样的作用的不同算法,我们如何判断这个算法的好坏呢?

我们很容易的想到可以通过这个算法计算某用例的时间与所额外占用的空间来判断。
但是对于不同的计算机而言,数据读取与处理的速度与方式是可以有很大的差别的。所以单纯的根据算法某次运行的时间与空间来判断算法的效率高低是没有说服力的。

所以,我们使用时间复杂度与空间复杂度这两个标准来衡量算法的效率的高低。
在本篇文章中将介绍时间复杂度:

时间复杂度

时间复杂度的定义

在计算机科学中,时间复杂度是一个函数,它定量的描述了一个算法运行的时间。

前面提到,要实际的测出算法的运行时间是很麻烦的,有很多的不确定变量。而算法运行的时间往往与其中语句的执行次数成正比,所以算法中基本语句的执行次数为算法的时间复杂度。

时间复杂度的函数就是基本语句数量与相关变量之间的数学关系式。

例如:

int fun(int n)
{int i = 0;int j = 0;int count = 0;for (i = 0; i < n; i++){for (j = 0; j < n; j++){count++;}}for (i = 0; i < 2 * n; i++){count++;}int m = 10;while (m--){count++;}return count;
}

在这段代码中:

基本语句的数量与变量n与变量m有关,而m的值是恒定的。
所以我们可以得到这个函数的时间复杂度的数学表达式为 n^2+2*n+10。

虽然对于上面的代码而言,找到精确的数学表达式来表示时间复杂度是很容易的,但是对于一些比较复杂的算法而言,想要找到精确的函数是很困难的。所以我们使用大O表示法来表示时间复杂度的大概值。

时间复杂度的大O表示法

大O符号是用于描述函数渐进行为的数学符号。

我们在使用大O表示法表示时间复杂度时,去掉对结果影响不大的项即可。
大O表示法的转换规则如下:

1、用常数1表示算法中的所有加法常数;
2、在修改后的数学表达式中只保留最高项;
3、如果最高项存在且不是1,则去掉该最高项的系数。
得到的结果就是大O阶。

对于上面的fun函数:
我们已经得到了该数学表达式:n^2+2*n+10。
首先将常数10改为1;再将最高项保留,即n^2;这一项的系数为1。
所以大O阶就为 O(n^2)

另外,某些算法在运行时对于不同的用例可能会有不同的情况。这时,我们采取最慢的情况来计算时间复杂度。

实例

在实际用大O阶表示时间复杂度的时候,我们其实并不用通过精确的数学表达式来推出,只需要将该算法基本语句的量级表示出来即可。例如对数级(log n)、正比例级(n)、次方级(n^2)、指数级(2^n)等。这些量级都是可以用函数图像表示出来的:

例如上面的fun函数的量级就是n^2级的。

而确认量级的最佳途径往往是画图,接下来将通过几个栗子来说明:

test1

void test1(int N)
{int count = 0;for (int k = 0; k < 100; ++k){++count;}printf("%d\n", count);
}

在这段代码中:
显然,算法的基本操作的数量与k相关。

k的值从0开始随着算法的执行递增1,到100终止。所以我们可以画出它大概的图像:

根据大O阶表示法,这个算法的时间复杂度就是O(1)。

test2

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次基本语句即可:

最坏的情况是完全降序的排列,此时就需要完全执行每一个基本语句,需要执行n^n次:

test3

int BinarySearch(int* a, int n, int x)
{assert(a);int begin = 0;int end = n - 1;// [begin, end]:begin和end是左闭右闭区间,因此有=号while (begin <= end){int mid = begin + ((end - begin) >> 1);if (a[mid] < x)begin = mid + 1;else if (a[mid] > x)end = mid - 1;elsereturn mid;}return -1;
}

这段代码就是经典的二分查找算法:

对于二分查找,是从n开始每次范围减少一半,知道剩余1个元素。
所以1乘以2的查找次数次方就是n,即需要执行log n次。我们就可以画出关系图:

需要注意的是,由于书写较麻烦,对于log以2为底n的对数,所以可以用log n表示。

test4

long long Fac(size_t N)
{if (0 == N)return 1;return Fac(N - 1) * N;
}

这是一个函数递归的算法:

将N-1的值再传给函数本身,直到N为0时终止递归。
很明显,该算法每次递归N递减1,所以执行N次基本语句:

test5

long long Fib(size_t N)
{if (N < 3)return 1;return Fib(N - 1) + Fib(N - 2);
}

这是一个递归实现斐波那契数列的算法:

对于该算法,每次递归都会引起两次递归,即两次基本语句(N-1与N-2)。直到参数<3终止。
我们可以先画出这个算法的程序图:

不难发现,基本语句的量级是指数增长的,所以该算法的时间复杂度为O(2^n):

总结

到此,关于时间复杂度的知识就介绍完了。
在下一篇文章中将详细介绍空间复杂度的相关知识,希望持续关注哦

如果大家认为我对某一部分没有介绍清楚或者某一部分出了问题,欢迎大家在评论区提出

如果本文对你有帮助,希望一键三连哦

希望与大家共同进步哦

时间复杂度(超详解+例题)相关推荐

  1. 空间复杂度(超详解+例题)

    全文目录 引言 空间复杂度 例题 test1 test2(冒泡排序) test3(求阶乘) test4(斐波那契数列) 总结 引言 在上一篇文章中,我们提到判断一个算法的好坏的标准是时间复杂度与空间复 ...

  2. Android vector标签 PathData 画图超详解

    此文章来源于https://www.cnblogs.com/yuhanghzsd/p/5466846.html点击打开链接 Android vector标签 PathData 画图超详解 SVG是一种 ...

  3. Mybatis案例超详解

    Mybatis案例超详解 前言: 本来是想像之前一样继续跟新Mybatis,但由于种种原因,迟迟没有更新,快开学了,学了一个暑假,博客也更新了不少,我觉得我得缓缓,先整合一些案例练练,等我再成熟点理解 ...

  4. python控制手机模拟器_Appium+python自动化之连接模拟器并启动淘宝APP(超详解)...

    简介 上一篇讲解完模拟器的安装.配置好以后,就好比我们手机已经买好,并且系统已经做好了,就差我们用数据线和电脑连接开始实战了,这篇宏哥就带着小伙伴们和童鞋们趁热打铁,讲解和分享一下如何连接模拟器(电脑 ...

  5. js打印三角形超详解

    js打印三角形超详解 j控制星星的总行数,i控制每行星星的打印个数 打印图形如下: (1) (2) //str=""用来存储星星// 理解步骤1:在一行输出6个星星如何操作,在循环 ...

  6. 线性规划之单纯形法【超详解+图解】-转载

    线性规划之单纯形法[超详解+图解] 目录 1.作用 2.线性规划的一般形式 5.1几何意义 5.2如何判断最优 5.3如何选择新的基变量 5.4如何选择被替换的基变量 5.5终止条件 标准型: 转化为 ...

  7. 【平衡小车制作】(七)串级PID调参及平衡成果展示(超详解)

      大家好,我是小政.本篇文章我将针对PID调参进行详细的讲解,让每位小伙伴能够对比例.积分.微分三个参数如何调节有更加清晰的理解. 一.调参步骤 确立机械中值 直立环(内环)--Kp极性.Kp大小. ...

  8. 蓝牙模块XY-MBD07A的介绍及使用方法(超详解)

    蓝牙模块XY-MBD07A的介绍及使用方法(超详解) 蓝牙XY-MBD07A是主从一体的蓝牙串口模块,简单的说,当蓝牙设备与蓝牙设备配对连接成功后,我们可以忽视蓝牙内部的通信协议,直接将将蓝牙当做串口 ...

  9. C/C++实现蛇形矩阵(超详解)【沈七】

    C/C++实现蛇形矩阵(超详解) 题目链接 题目描述 输入样例 题解部分 完整代码 完结散花 悄悄告诉你: 参考文章 萌新报道! 唤我沈七就行嘿嘿. 大一软件工程在读. 菜鸡蒟蒻想在博客中记录一些算法 ...

最新文章

  1. python xmxl 无法启动_问题引发由于与GI相关的python脚本中的错误,Gnome终端无法启动...
  2. mysql 历史版本下载
  3. jzoj3896-战争游戏【tarjan,割点,点双联通分量】
  4. Atitit 数据控制语言与权限  DCL
  5. java私塾跟我学系列_java 私塾作业
  6. CMD启动MySQL常用命令
  7. 【安卓学习积累】Android连续点击事件的实现
  8. gwas snp 和_新的高密度玉米SNP芯片可用于基因组选择、GWAS和群体遗传学
  9. stLFR(single tube Long Fragment Read)介绍
  10. Android音视频开发学习
  11. 微信小程序使用阿里彩色图标
  12. C语言经典例题100道
  13. 昆明市谷歌高清卫星地图下载
  14. oracle中间人投毒漏洞,Oracle Database Server 'TNS Listener'远程数据投毒漏洞(CVE-2012-1675)的完美解决方法...
  15. 一招恢复删除的微信好友
  16. 密码打码就安全了吗?这款星标 20K 的去 『马赛克』 开源神器,用 AI 一秒还原高清原图!...
  17. 26-基于单片机的传送带计数系统
  18. C# 日期转换AM/PM
  19. 柚子壁纸为什么自动安装_火爆抖音的时间罗盘壁纸,iPhone和安卓都支持!
  20. Flask之jinja2模板(二)

热门文章

  1. Linux下minicom配置
  2. OCR 图像智能字符识别技术
  3. 使用二维数组和函数解决八皇后问题(c++)
  4. uniapp ios原生插件开发之插件包格式(package.json)
  5. UML--顺序图绘制
  6. 【大数据】海量数据处理方法
  7. web开发框架_Web开发的最佳PHP框架
  8. 老男孩-Python之路,Day2 - Python基础2
  9. Java变量-Java变量运算
  10. 成长笔记4:教育是什么