算法(Algorithm)是指用来操作数据、解决程序问题的一组方法。对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,比如排序就有前面的十大经典排序和几种奇葩排序,虽然结果相同,但在过程中消耗的资源和时间却会有很大的区别,比如快速排序与猴子排序:)。

那么我们应该如何去衡量不同算法之间的优劣呢?

主要还是从算法所占用的「时间」和「空间」两个维度去考量。

  • 时间维度:是指执行当前算法所消耗的时间,我们通常用「时间复杂度」来描述。

  • 空间维度:是指执行当前算法需要占用多少内存空间,我们通常用「空间复杂度」来描述。

本小节将从「时间」的维度进行分析。

什么是大O

当看「时间」二字,我们肯定可以想到将该算法程序运行一篇,通过运行的时间很容易就知道复杂度了。

这种方式可以吗?当然可以,不过它也有很多弊端。

比如程序员小吴的老式电脑处理10w数据使用冒泡排序要几秒,但读者的iMac Pro 可能只需要0.1s,这样的结果误差就很大了。更何况,有的算法运行时间要很久,根本没办法没时间去完整的运行,还是比如猴子排序:)。

那有什么方法可以严谨的进行算法的时间复杂度分析呢?

有的!

「 远古 」的程序员大佬们提出了通用的方法:「 大O符号表示法 」,即 T(n) = O(f(n))

其中 n 表示数据规模 ,O(f(n))表示运行算法所需要执行的指令数,和f(n)成正比。

上面公式中用到的 Landau符号是由德国数论学家保罗·巴赫曼(Paul Bachmann)在其1892年的著作《解析数论》首先引入,由另一位德国数论学家艾德蒙·朗道(Edmund Landau)推广。Landau符号的作用在于用简单的函数来描述复杂函数行为,给出一个上或下(确)界。在计算算法复杂度时一般只用到大O符号,Landau符号体系中的小o符号、Θ符号等等比较不常用。这里的O,最初是用大写希腊字母,但现在都用大写英语字母O;小o符号也是用小写英语字母o,Θ符号则维持大写希腊字母Θ。

注:本文用到的算法中的界限指的是最低的上界。

常见的时间复杂度量级

我们先从常见的时间复杂度量级进行大O的理解:

  • 常数阶O(1)

  • 线性阶O(n)

  • 平方阶O(n²)

  • 对数阶O(logn)

  • 线性对数阶O(nlogn)

O(1)

无论代码执行了多少行,其他区域不会影响到操作,这个代码的时间复杂度都是O(1)

1void swapTwoInts(int &a, int &b){2  int temp = a;3  a = b;4  b = temp;5}

O(n)

在下面这段代码,for循环里面的代码会执行 n 遍,因此它消耗的时间是随着 n 的变化而变化的,因此可以用O(n)来表示它的时间复杂度。

1int sum ( int n ){2   int ret = 0;3   for ( int i = 0 ; i <= n ; i ++){4      ret += i;5   }6   return ret;7}

特别一提的是 c * O(n) 中的 c 可能小于 1 ,比如下面这段代码:

1void reverse ( string &s ) {2    int n = s.size();3    for (int i = 0 ; i < n/2 ; i++){4      swap ( s[i] , s[n-1-i]);5    }6}

O(n²)


当存在双重循环的时候,即把 O(n) 的代码再嵌套循环一遍,它的时间复杂度就是 O(n²) 了。

 1void selectionSort(int arr[],int n){ 2   for(int i = 0; i < n ; i++){ 3     int minIndex = i; 4     for (int j = i + 1; j < n ; j++ ) 5       if (arr[j] < arr[minIndex]) 6           minIndex = j; 7 8     swap ( arr[i], arr[minIndex]); 9   }10}

这里简单的推导一下

  • 当 i = 0 时,第二重循环需要运行 (n - 1) 次
  • 当 i = 1 时,第二重循环需要运行 (n - 2) 次
  • 。。。。。。

不难得到公式:

1(n - 1) + (n - 2) + (n - 3) + ... + 02= (0 + n - 1) * n / 23= O (n ^2)

当然并不是所有的双重循环都是 O(n²),比如下面这段输出 30n 次 Hello,五分钟学算法:)的代码。

1void printInformation (int n ){2   for (int i = 1 ; i <= n ; i++)3        for (int j = 1 ; j <= 30 ; j ++)4           cout<< "Hello,五分钟学算法:)"<< endl;5}

O(logn)

 1int binarySearch( int arr[], int n , int target){ 2  int l = 0, r = n - 1; 3  while ( l <= r) { 4    int mid = l + (r - l) / 2; 5    if (arr[mid] == target) return mid; 6    if (arr[mid] > target ) r = mid - 1; 7    else l = mid + 1; 8  } 9  return -1;10}

在二分查找法的代码中,通过while循环,成 2 倍数的缩减搜索范围,也就是说需要经过 log2^n 次即可跳出循环。

同样的还有下面两段代码也是 O(logn) 级别的时间复杂度。

 1  // 整形转成字符串 2  string intToString ( int num ){ 3   string s = ""; 4   // n 经过几次“除以10”的操作后,等于0 5   while (num ){ 6    s += '0' + num%10; 7    num /= 10; 8   } 9   reverse(s)10   return s;11  }
1void hello (int n ) {2   // n 除以几次 2 到 13   for ( int sz = 1; sz < n ; sz += sz) 4     for (int i = 1; i < n; i++)5        cout<< "Hello,五分钟学算法:)"<< endl;6}

O(nlogn)

将时间复杂度为O(logn)的代码循环N遍的话,那么它的时间复杂度就是 n * O(logn),也就是了O(nlogn)。

1void hello (){2  for( m = 1 ; m < n ; m++){3    i = 1;4    while( i < n ){5        i = i * 2;6    }7   }8}

更多复杂度分析内容可以在公众号 五分钟学算法 获取

转载于:https://www.cnblogs.com/fivestudy/p/10113337.html

看动画轻松理解时间复杂度(一)相关推荐

  1. 看动画轻松理解“递归”与“动态规划”

    作者 | 程序员小吴 来源 | 五分钟学算法 在学习「数据结构和算法」的过程中,因为人习惯了平铺直叙的思维方式,所以「递归」与「动态规划」这种带循环概念(绕来绕去)的往往是相对比较难以理解的两个抽象知 ...

  2. c 递归下降识别程序_看动画轻松理解递归与动态规划

    在学习「数据结构和算法」的过程中,因为人习惯了平铺直叙的思维方式,所以「递归」与「动态规划」这种带循环概念(绕来绕去)的往往是相对比较难以理解的两个抽象知识点. 程序员小吴打算使用动画的形式来帮助理解 ...

  3. 看动画轻松理解「链表」实现「LRU缓存淘汰算法」

    作者 | 程序员小吴,哈工大学渣,目前正在学算法,开源项目 「 LeetCodeAnimation 」5500star,GitHub Trending 榜连续一月第一. 本文为 AI科技大本营投稿文章 ...

  4. 看动画轻松理解「Trie树」

    作者 | 程序员小吴 责编 | 胡巍巍 扎心!"我学了半年 Python,还是找不到工作" https://edu.csdn.net/topic/python115?utm_sou ...

  5. 看动画轻松理解「链表」实现「 LRU 缓存淘汰算法」

    作者 | 吴至波 责编 | 胡巍巍 快速挑战Python全栈工程师: https://edu.csdn.net/topic/python115?utm_source=csdn_bw 前几节学习了「链表 ...

  6. 看图轻松理解数据结构与算法系列(合并排序)

    前言 推出一个新系列,<看图轻松理解数据结构和算法>,主要使用图片来描述常见的数据结构和算法,轻松阅读并理解掌握.本系列包括各种堆.各种队列.各种列表.各种树.各种图.各种排序等等几十篇的 ...

  7. 看图轻松理解数据结构与算法系列(2-3树)

    前言 推出一个新系列,<看图轻松理解数据结构和算法>,主要使用图片来描述常见的数据结构和算法,轻松阅读并理解掌握.本系列包括各种堆.各种队列.各种列表.各种树.各种图.各种排序等等几十篇的 ...

  8. 看图轻松理解斐波那契数列

    前言 推出一个新系列,<看图轻松理解数据结构和算法>,主要使用图片来描述常见的数据结构和算法,轻松阅读并理解掌握.本系列包括各种堆.各种队列.各种列表.各种树.各种图.各种排序等等几十篇的 ...

  9. 认沽期权看图轻松理解

    正如二级市场上有买方也有卖方,同理,与认购期权相对应的,是认沽期权.本篇文章就给大家解释一下什么是认沽期权.我们同样来看组图: 以上就是认沽期权的举例说明和解释

最新文章

  1. mysql noinstall 布署_mysql-noinstall.zip免安装版的优化配置和精简
  2. Using POI to replace elements in WORD(.docx/.doc)(使用POI替换word中的特定字符/文字)【改进】...
  3. QML和C ++之间的数据类型转换---枚举
  4. jmeter难吗_Jmeter集成Jira提交缺陷
  5. jsp里加java代码,利用静态内部类为您的代码添加辅助功能-JSP教程,Java技巧及代码...
  6. spring整合使用activemq
  7. 云图说丨“真人?机器?傻傻分不清!” WAF Bot管理,带你慧眼辨“精”!
  8. 刚公布完价格就被骂?这款新机有点惨...
  9. Cocoa编程开发者手册
  10. 7大编程误区,你避开了吗?
  11. [LeetCode] Spiral Matrix II
  12. 服务器应用层次划分,服务器按应用层次划分的话可以分为哪几种?
  13. 交换机的基本交换配置
  14. pandas_空值填充|重复数据|异常数据
  15. 科来网络回溯分析系统-回溯追踪ARP扫描攻击
  16. python list 添加噪声_在python中为信号添加噪声
  17. php45欧米伽_PHP中的数字格式5.5到5.50 - php
  18. RFM 客户价值分析
  19. oracle中的start with
  20. 英国AI创业公司Hazy获180万美元种子轮融资

热门文章

  1. 树莓派使用STEP3:更换镜像源
  2. CSS之基于视窗单位的排版
  3. C 语言调用CPU指令,CPU 1214C中 TSEND_C指令 最多可以使用几次-工业支持中心-西门子中国...
  4. python web自动化测试实验报告_Python:web自动化测试
  5. GDAL读取Shp问题解决:Unable to open EPSG support file gcs.csv
  6. 【软工项目组】第九次会议
  7. 1+2+3+n;1*1*2*n
  8. Android 触摸手势基础 官方文档概览
  9. SAP RFC 获取BDC 消息文本的实现
  10. Java poi读取,写入Excel2003